├── .gitignore ├── LICENSE.md ├── Listing_10.1.rb ├── Listing_10.10.rb ├── Listing_10.11.rb ├── Listing_10.12.rb ├── Listing_10.13.rb ├── Listing_10.14.rb ├── Listing_10.2.rb ├── Listing_10.3.rb ├── Listing_10.4.rb ├── Listing_10.5.rb ├── Listing_10.6.rb ├── Listing_10.7.irb ├── Listing_10.8.irb ├── Listing_10.9.irb ├── Listing_11.1.rb ├── Listing_11.10.html ├── Listing_11.11.rb ├── Listing_11.12.rb ├── Listing_11.13.rb ├── Listing_11.14.rb ├── Listing_11.15.txt ├── Listing_11.16.txt ├── Listing_11.17.rb ├── Listing_11.18.rb ├── Listing_11.19.txt ├── Listing_11.2.rb ├── Listing_11.20.rhtml ├── Listing_11.21.rhtml ├── Listing_11.22.rhtml ├── Listing_11.23.html ├── Listing_11.24.txt ├── Listing_11.25.rhtml ├── Listing_11.26.txt ├── Listing_11.27.rb ├── Listing_11.28.txt ├── Listing_11.29.rb ├── Listing_11.3.txt ├── Listing_11.30.txt ├── Listing_11.31.rhtml ├── Listing_11.32.rb ├── Listing_11.33.txt ├── Listing_11.34.rhtml ├── Listing_11.35.rb ├── Listing_11.36.text ├── Listing_11.37.rhtml ├── Listing_11.38.rhtml ├── Listing_11.39.txt ├── Listing_11.4.rb ├── Listing_11.40.rhtml ├── Listing_11.41.txt ├── Listing_11.42.rb ├── Listing_11.43.rb ├── Listing_11.44.rb ├── Listing_11.45.rhtml ├── Listing_11.46.rb ├── Listing_11.47.rb ├── Listing_11.48.rhtml ├── Listing_11.49.rhtml ├── Listing_11.5.rb ├── Listing_11.50.rb ├── Listing_11.51.rb ├── Listing_11.52.rb ├── Listing_11.53.txt ├── Listing_11.54.rb ├── Listing_11.55.txt ├── Listing_11.56.rhtml ├── Listing_11.57.txt ├── Listing_11.58.rhtml ├── Listing_11.59.rhtml ├── Listing_11.6.rb ├── Listing_11.60.rhtml ├── Listing_11.61.txt ├── Listing_11.7.rhtml ├── Listing_11.8.rhtml ├── Listing_11.9.rhtml ├── Listing_2.1.txt ├── Listing_2.10.txt ├── Listing_2.11.txt ├── Listing_2.12.rb ├── Listing_2.13.rb ├── Listing_2.2.irb ├── Listing_2.3.rb ├── Listing_2.4.irb ├── Listing_2.5.rb ├── Listing_2.6.rb ├── Listing_2.7.bash ├── Listing_2.8.rb ├── Listing_2.9.txt ├── Listing_3.1.irb ├── Listing_3.10.irb ├── Listing_3.11.irb ├── Listing_3.12.irb ├── Listing_3.13.irb ├── Listing_3.14.irb ├── Listing_3.15.irb ├── Listing_3.16.irb ├── Listing_3.17.irb ├── Listing_3.18.irb ├── Listing_3.19.js ├── Listing_3.2.irb ├── Listing_3.20.irb ├── Listing_3.3.irb ├── Listing_3.4.irb ├── Listing_3.5.irb ├── Listing_3.6.irb ├── Listing_3.7.irb ├── Listing_3.8.irb ├── Listing_3.9.irb ├── Listing_4.1.irb ├── Listing_4.2.irb ├── Listing_4.3.irb ├── Listing_4.4.irb ├── Listing_5.1.irb ├── Listing_5.2.rb ├── Listing_5.3.rb ├── Listing_5.4.rb ├── Listing_5.5.rb ├── Listing_5.6.irb ├── Listing_5.7.rb ├── Listing_5.8.rb ├── Listing_5.9.rb ├── Listing_6.1.rb ├── Listing_6.10.rb ├── Listing_6.11.rb ├── Listing_6.12.irb ├── Listing_6.13.js ├── Listing_6.14.irb ├── Listing_6.15.rb ├── Listing_6.16.rb ├── Listing_6.17.rb ├── Listing_6.18.rb ├── Listing_6.19.rb ├── Listing_6.2.rb ├── Listing_6.3.rb ├── Listing_6.4.rb ├── Listing_6.5.rb ├── Listing_6.6.rb ├── Listing_6.7.rb ├── Listing_6.8.rb ├── Listing_6.9.rb ├── Listing_7.1.rb ├── Listing_7.10.rb ├── Listing_7.2.rb ├── Listing_7.3.rb ├── Listing_7.4.rb ├── Listing_7.5.rb ├── Listing_7.6.rb ├── Listing_7.7.rb ├── Listing_7.8.rb ├── Listing_7.9.rb ├── Listing_8.1.rb ├── Listing_8.10.rb ├── Listing_8.11.rb ├── Listing_8.12.rb ├── Listing_8.13.rb ├── Listing_8.14.irb ├── Listing_8.15.rb ├── Listing_8.16.irb ├── Listing_8.17.rb ├── Listing_8.18.rb ├── Listing_8.19.rb ├── Listing_8.2.rb ├── Listing_8.20.rb ├── Listing_8.21.rb ├── Listing_8.22.rb ├── Listing_8.23.rb ├── Listing_8.24.rb ├── Listing_8.3.rb ├── Listing_8.4.rb ├── Listing_8.5.rb ├── Listing_8.6.rb ├── Listing_8.7.rb ├── Listing_8.8.irb ├── Listing_8.9.rb ├── Listing_9.1.txt ├── Listing_9.10.rb ├── Listing_9.11.rb ├── Listing_9.12.rb ├── Listing_9.13.text ├── Listing_9.14.rb ├── Listing_9.15.text ├── Listing_9.16.rb ├── Listing_9.17.rb ├── Listing_9.18.rb ├── Listing_9.19.text ├── Listing_9.2.rb ├── Listing_9.20.rb ├── Listing_9.21.rb ├── Listing_9.22.rb ├── Listing_9.23.text ├── Listing_9.24.rb ├── Listing_9.25.text ├── Listing_9.26.rb ├── Listing_9.27.text ├── Listing_9.28.rb ├── Listing_9.29.text ├── Listing_9.3.rb ├── Listing_9.30.rb ├── Listing_9.31.text ├── Listing_9.32.rb ├── Listing_9.33.text ├── Listing_9.34.rb ├── Listing_9.35.rb ├── Listing_9.36.rb ├── Listing_9.37.text ├── Listing_9.38.rb ├── Listing_9.39.rb ├── Listing_9.4.rb ├── Listing_9.40.rb ├── Listing_9.5.txt ├── Listing_9.6.rb ├── Listing_9.7.txt ├── Listing_9.8.rb ├── Listing_9.9.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ``` 2 | The MIT License 3 | 4 | Copyright (c) 2022 Michael Hartl 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | ``` 24 | -------------------------------------------------------------------------------- /Listing_10.1.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require '_palindrome' 3 | 4 | puts "hello, world!" 5 | -------------------------------------------------------------------------------- /Listing_10.10.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'open-uri' 3 | require 'nokogiri' 4 | 5 | # Returns the paragraphs from a Wikipedia link, stripped of reference numbers. 6 | # Especially useful for text-to-speech (both native and foreign). 7 | 8 | url = ARGV[0] 9 | 10 | puts url 11 | -------------------------------------------------------------------------------- /Listing_10.11.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'open-uri' 3 | require 'nokogiri' 4 | 5 | # Returns the paragraphs from a Wikipedia link, stripped of reference numbers. 6 | # Especially useful for text-to-speech (both native and foreign). 7 | 8 | url = ARGV[0] 9 | doc = Nokogiri::HTML(URI.open(url).read) 10 | -------------------------------------------------------------------------------- /Listing_10.12.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'open-uri' 3 | require 'nokogiri' 4 | 5 | # Returns the paragraphs from a Wikipedia link, stripped of reference numbers. 6 | # Especially useful for text-to-speech (both native and foreign). 7 | 8 | url = ARGV[0] 9 | doc = Nokogiri::HTML(URI.open(url).read) 10 | doc.css('.reference').each { |reference| reference.remove } 11 | -------------------------------------------------------------------------------- /Listing_10.13.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'open-uri' 3 | require 'nokogiri' 4 | 5 | # Returns the paragraphs from a Wikipedia link, stripped of reference numbers. 6 | # Especially useful for text-to-speech (both native and foreign). 7 | 8 | url = ARGV[0] 9 | doc = Nokogiri::HTML(URI.open(url).read) 10 | doc.css('.reference').each { |reference| reference.remove } 11 | content_array = doc.css('p').map { |paragraph| paragraph.content } 12 | puts content_array.join("\n") 13 | -------------------------------------------------------------------------------- /Listing_10.14.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'open-uri' 3 | require 'nokogiri' 4 | 5 | # Returns the paragraphs from a Wikipedia link, stripped of reference numbers. 6 | # Especially useful for text-to-speech (both native and foreign). 7 | 8 | url = ARGV[0] 9 | doc = Nokogiri::HTML(URI.open(url).read) 10 | doc.css('.reference').each(&:remove) 11 | puts doc.css('p').map(&:content).join("\n") 12 | -------------------------------------------------------------------------------- /Listing_10.2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require '_palindrome' 3 | 4 | text = File.read("phrases.txt") 5 | text.split("\n").each do |line| 6 | if line.palindrome? 7 | puts "palindrome detected: #{line}" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Listing_10.3.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require '_palindrome' 3 | 4 | lines = File.readlines("phrases.txt") 5 | lines.each do |line| 6 | if line.palindrome? 7 | puts "palindrome detected: #{line}" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Listing_10.4.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require '_palindrome' 3 | 4 | lines = File.readlines("phrases.txt") 5 | lines.each do |line| 6 | if line.palindrome? 7 | puts "palindrome detected: #{line}" 8 | end 9 | end 10 | 11 | palindromes = lines.select(&:palindrome?) 12 | File.write('palindromes_file.txt', palindromes.join) 13 | -------------------------------------------------------------------------------- /Listing_10.5.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require '_palindrome' 3 | 4 | palindromes = File.readlines('phrases.txt').select(&:palindrome?) 5 | palindromes.each { |palindrome| puts "palindrome detected: #{palindrome}" } 6 | File.write('palindromes_file.txt', palindromes.join) 7 | -------------------------------------------------------------------------------- /Listing_10.6.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require '_palindrome' 3 | require 'open-uri' 4 | 5 | lines = open('https://cdn.learnenough.com/phrases.txt').readlines 6 | lines.each do |line| 7 | if line.palindrome? 8 | puts "palindrome detected: #{line}" 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /Listing_10.7.irb: -------------------------------------------------------------------------------- 1 | >> require 'nokogiri' 2 | >> html = '

lorem1

ipsum

' 3 | >> doc = Nokogiri::HTML(html) 4 | => #> doc.css('.reference').each { |reference| reference.remove } 2 | -------------------------------------------------------------------------------- /Listing_10.9.irb: -------------------------------------------------------------------------------- 1 | >> doc.css('p').map { |paragraph| paragraph.content } 2 | => ["lorem", "ipsum"] 3 | -------------------------------------------------------------------------------- /Listing_11.1.rb: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '3.1.1' # Change this line if you're using a different Ruby version. 4 | 5 | gem 'sinatra', '2.2.0' 6 | gem 'puma', '5.6.2' 7 | gem 'rerun', '0.13.1' 8 | -------------------------------------------------------------------------------- /Listing_11.10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /Listing_11.11.rb: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '3.1.1' # Change this line if you're using a different Ruby version. 4 | 5 | gem 'sinatra', '2.2.0' 6 | gem 'puma', '5.6.2' 7 | gem 'rerun', '0.13.1' 8 | 9 | group :test do 10 | gem 'minitest', '5.15.0' 11 | gem 'minitest-reporters', '1.5.0' 12 | gem 'rack-test', '1.1.0' 13 | gem 'rake', '13.0.6' 14 | gem 'nokogiri', '1.13.3' 15 | end 16 | -------------------------------------------------------------------------------- /Listing_11.12.rb: -------------------------------------------------------------------------------- 1 | ENV['RACK_ENV'] = 'test' 2 | 3 | require_relative '../app' 4 | require 'rack/test' 5 | require 'nokogiri' 6 | require 'minitest/autorun' 7 | require 'minitest/reporters' 8 | Minitest::Reporters.use! 9 | -------------------------------------------------------------------------------- /Listing_11.13.rb: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | Rake::TestTask.new do |t| 4 | t.pattern = 'test/*_test.rb' 5 | t.warning = false 6 | end 7 | 8 | task :default => [:test] 9 | -------------------------------------------------------------------------------- /Listing_11.14.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_index 11 | get '/' 12 | assert last_response.ok? 13 | end 14 | 15 | def test_about 16 | get '/about' 17 | assert last_response.ok? 18 | end 19 | 20 | def test_palindrome 21 | get '/palindrome' 22 | assert last_response.ok? 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /Listing_11.15.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 3 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.16.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake 2 | 3 tests, 3 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.17.rb: -------------------------------------------------------------------------------- 1 | ENV['RACK_ENV'] = 'test' 2 | 3 | require_relative '../app' 4 | require 'rack/test' 5 | require 'nokogiri' 6 | require 'minitest/autorun' 7 | require 'minitest/reporters' 8 | Minitest::Reporters.use! 9 | 10 | # Returns the document. 11 | def doc(response) 12 | Nokogiri::HTML(response.body) 13 | end 14 | -------------------------------------------------------------------------------- /Listing_11.18.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_index 11 | get '/' 12 | assert last_response.ok? 13 | assert doc(last_response).at_css('h1') 14 | end 15 | 16 | def test_about 17 | get '/about' 18 | assert last_response.ok? 19 | assert doc(last_response).at_css('h1') 20 | end 21 | 22 | def test_palindrome 23 | get '/palindrome' 24 | assert last_response.ok? 25 | assert doc(last_response).at_css('h1') 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /Listing_11.19.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 6 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.2.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | 'hello, world!' 5 | end 6 | -------------------------------------------------------------------------------- /Listing_11.20.rhtml: -------------------------------------------------------------------------------- 1 |

Sample Sinatra App

2 | 3 |

4 | This is the sample Sinatra app for 5 | Learn Enough Ruby 6 | to Be Dangerous. Learn more on the About page. 7 |

8 | 9 |

10 | Click the Sator 11 | Square below to run the custom Palindrome 12 | Detector. 13 |

14 | 15 | 16 | Sator Square 17 | 18 | -------------------------------------------------------------------------------- /Listing_11.21.rhtml: -------------------------------------------------------------------------------- 1 |

About

2 | 3 |

4 | This site is the final application in 5 | Learn Enough Ruby 6 | to Be Dangerous 7 | by Michael Hartl, 8 | a tutorial introduction to the 9 | Ruby programing language that 10 | is part of 11 | LearnEnough.com. 12 |

13 | 14 |

15 | Learn Enough Ruby to Be Dangerous is a natural prerequisite to 16 | the Ruby on Rails 17 | Tutorial, a book and video series that is one of the leading 18 | introductions to web development. Learn Enough Ruby is also an 19 | excellent choice after the Rails Tutorial for those who 20 | prefer to start with the latter first. 21 |

22 | -------------------------------------------------------------------------------- /Listing_11.22.rhtml: -------------------------------------------------------------------------------- 1 |

Palindrome Detector

2 | 3 |

This will be the palindrome detector.

4 | -------------------------------------------------------------------------------- /Listing_11.23.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /Listing_11.24.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 6 assertions, 3 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.25.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | <%= yield %> 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /Listing_11.26.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 6 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.27.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_index 11 | get '/' 12 | assert last_response.ok? 13 | assert doc(last_response).at_css('h1') 14 | title_content = doc(last_response).at_css('title').content 15 | assert_equal "Learn Enough Ruby Sample App", title_content 16 | end 17 | 18 | def test_about 19 | get '/about' 20 | assert last_response.ok? 21 | assert doc(last_response).at_css('h1') 22 | title_content = doc(last_response).at_css('title').content 23 | assert_equal "Learn Enough Ruby Sample App", title_content 24 | end 25 | 26 | def test_palindrome 27 | get '/palindrome' 28 | assert last_response.ok? 29 | assert doc(last_response).at_css('h1') 30 | title_content = doc(last_response).at_css('title').content 31 | assert_equal "Learn Enough Ruby Sample App", title_content 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /Listing_11.28.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 9 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.29.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_index 11 | get '/' 12 | assert last_response.ok? 13 | assert doc(last_response).at_css('h1') 14 | title_content = doc(last_response).at_css('title').content 15 | assert_equal "Learn Enough Ruby Sample App | Home", title_content 16 | end 17 | 18 | def test_about 19 | get '/about' 20 | assert last_response.ok? 21 | assert doc(last_response).at_css('h1') 22 | title_content = doc(last_response).at_css('title').content 23 | assert_equal "Learn Enough Ruby Sample App | About", title_content 24 | end 25 | 26 | def test_palindrome 27 | get '/palindrome' 28 | assert last_response.ok? 29 | assert doc(last_response).at_css('h1') 30 | title_content = doc(last_response).at_css('title').content 31 | assert_equal "Learn Enough Ruby Sample App | Palindrome Detector", 32 | title_content 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /Listing_11.3.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rerun app.rb 2 | 3 | 12:10:10 [rerun] Palindrome_app launched 4 | 12:10:10 [rerun] Rerun (79556) running Palindrome_app (79575) 5 | == Sinatra (v2.0.3) has taken the stage on 4567 for development 6 | with backup from Thin 7 | Thin web server (v1.7.2 codename Bachmanity) 8 | Maximum connections set to 1024 9 | Listening on localhost:4567, CTRL+C to stop 10 | -------------------------------------------------------------------------------- /Listing_11.30.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 9 assertions, 3 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.31.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App | <%= @title %> 6 | . 7 | . 8 | . 9 | -------------------------------------------------------------------------------- /Listing_11.32.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | @title = 'Home' 5 | erb :index 6 | end 7 | 8 | get '/about' do 9 | @title = 'About' 10 | erb :about 11 | end 12 | 13 | get '/palindrome' do 14 | @title = 'Palindrome Detector' 15 | erb :palindrome 16 | end 17 | -------------------------------------------------------------------------------- /Listing_11.33.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 9 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.34.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App | <%= @title %> 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | 23 |
24 |
25 | <%= yield %> 26 |
27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /Listing_11.35.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_index 11 | get '/' 12 | assert last_response.ok? 13 | assert doc(last_response).at_css('h1') 14 | title_content = doc(last_response).at_css('title').content 15 | assert_equal "Learn Enough Ruby Sample App | Home", title_content 16 | assert doc(last_response).at_css('nav') 17 | end 18 | . 19 | . 20 | . 21 | end 22 | -------------------------------------------------------------------------------- /Listing_11.36.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 10 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.37.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App | <%= @title %> 6 | 7 | 9 | 10 | 11 | 14 |
15 |                             16 |
17 | <%= yield %> 18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /Listing_11.38.rhtml: -------------------------------------------------------------------------------- 1 |
2 | 9 |
10 | -------------------------------------------------------------------------------- /Listing_11.39.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 10 assertions, 1 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.4.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | 'goodbye, world!' 5 | end 6 | -------------------------------------------------------------------------------- /Listing_11.40.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App | <%= @title %> 6 | 7 | 9 | 10 | 11 | 14 |
15 | <%= erb :navigation %> 16 |
17 | <%= yield %> 18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /Listing_11.41.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 3 tests, 10 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.42.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def setup 11 | @base_title = "Learn Enough Ruby Sample App" 12 | end 13 | 14 | def test_index 15 | get '/' 16 | assert last_response.ok? 17 | assert doc(last_response).at_css('h1') 18 | title_content = doc(last_response).at_css('title').content 19 | assert_equal "#{@base_title} | Home", title_content 20 | end 21 | 22 | def test_about 23 | get '/about' 24 | assert last_response.ok? 25 | assert doc(last_response).at_css('h1') 26 | title_content = doc(last_response).at_css('title').content 27 | assert_equal "#{@base_title} | About", title_content 28 | end 29 | 30 | def test_palindrome 31 | get '/palindrome' 32 | assert last_response.ok? 33 | assert doc(last_response).at_css('h1') 34 | title_content = doc(last_response).at_css('title').content 35 | assert_equal "#{@base_title} | Palindrome Detector", title_content 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /Listing_11.43.rb: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '3.1.1' # Change this line if you're using a different Ruby version. 4 | 5 | gem 'sinatra', '2.2.0' 6 | gem 'puma', '5.6.2' 7 | gem 'rerun', '0.13.1' 8 | gem 'mhartl_palindrome', '0.1.0' 9 | 10 | group :test do 11 | gem 'minitest', '5.15.0' 12 | gem 'minitest-reporters', '1.5.0' 13 | gem 'rack-test', '1.1.0' 14 | gem 'rake', '13.0.6' 15 | gem 'nokogiri', '1.13.3' 16 | end 17 | 18 | -------------------------------------------------------------------------------- /Listing_11.44.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | require 'mhartl_palindrome' 3 | 4 | get '/' do 5 | @title = 'Home' 6 | erb :index 7 | end 8 | 9 | get '/about' do 10 | @title = 'About' 11 | erb :about 12 | end 13 | 14 | get '/palindrome' do 15 | @title = 'Palindrome Detector' 16 | erb :palindrome 17 | end 18 | -------------------------------------------------------------------------------- /Listing_11.45.rhtml: -------------------------------------------------------------------------------- 1 |

Palindrome Detector

2 | 3 |
4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /Listing_11.46.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | require 'mhartl_palindrome' 3 | 4 | get '/' do 5 | @title = 'Home' 6 | erb :index 7 | end 8 | 9 | get '/about' do 10 | @title = 'About' 11 | erb :about 12 | end 13 | 14 | get '/palindrome' do 15 | @title = 'Palindrome Detector' 16 | erb :palindrome 17 | end 18 | 19 | post '/check' do 20 | raise params.inspect 21 | end 22 | -------------------------------------------------------------------------------- /Listing_11.47.rb: -------------------------------------------------------------------------------- 1 | if @phrase.palindrome? 2 | puts "\"#{@phrase}\" is a palindrome!" 3 | else 4 | puts "\"#{@phrase}\" isn't a palindrome." 5 | end 6 | -------------------------------------------------------------------------------- /Listing_11.48.rhtml: -------------------------------------------------------------------------------- 1 | <% if @phrase.palindrome? %> 2 | "<%= @phrase %>" is a palindrome! 3 | <% else %> 4 | "<%= @phrase %>" isn't a palindrome! 5 | <% end %> 6 | -------------------------------------------------------------------------------- /Listing_11.49.rhtml: -------------------------------------------------------------------------------- 1 |

Palindrome Result

2 | 3 | <% if @phrase.palindrome? %> 4 |
5 |

"<%= @phrase %>" is a palindrome!

6 |
7 | <% else %> 8 |
9 |

"<%= @phrase %>" isn't a palindrome!

10 |
11 | <% end %> 12 | -------------------------------------------------------------------------------- /Listing_11.5.rb: -------------------------------------------------------------------------------- 1 | require './app' 2 | run Sinatra::Application 3 | -------------------------------------------------------------------------------- /Listing_11.50.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | require 'mhartl_palindrome' 3 | 4 | get '/' do 5 | @title = 'Home' 6 | erb :index 7 | end 8 | 9 | get '/about' do 10 | @title = 'About' 11 | erb :about 12 | end 13 | 14 | get '/palindrome' do 15 | @title = 'Palindrome Detector' 16 | erb :palindrome 17 | end 18 | 19 | post '/check' do 20 | @phrase = params[:phrase] 21 | erb :result 22 | end 23 | -------------------------------------------------------------------------------- /Listing_11.51.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_form_presence 11 | get '/palindrome' 12 | assert doc(last_response).at_css('form') 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_11.52.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_form_presence 11 | get '/palindrome' 12 | assert doc(last_response).at_css('form') 13 | end 14 | 15 | def test_non_palindrome_submission 16 | post '/check', phrase: "Not a palindrome" 17 | assert_includes doc(last_response).at_css('p').content, "isn't a palindrome" 18 | end 19 | 20 | def test_palindrome_submission 21 | post '/check', phrase: "Able was I, ere I saw Elba." 22 | assert_includes doc(last_response).at_css('p').content, "is a palindrome" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /Listing_11.53.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 6 tests, 15 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.54.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | class PalindromeAppTest < Minitest::Test 4 | include Rack::Test::Methods 5 | 6 | def app 7 | Sinatra::Application 8 | end 9 | 10 | def test_form_presence 11 | get '/palindrome' 12 | assert doc(last_response).at_css('form') 13 | end 14 | 15 | def test_non_palindrome_submission 16 | post '/check', phrase: "Not a palindrome" 17 | assert_includes doc(last_response).at_css('p').content, "isn't a palindrome" 18 | assert doc(last_response).at_css('form') 19 | end 20 | 21 | def test_palindrome_submission 22 | post '/check', phrase: "Able was I, ere I saw Elba." 23 | assert_includes doc(last_response).at_css('p').content, "is a palindrome" 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /Listing_11.55.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 6 tests, 16 assertions, 1 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.56.rhtml: -------------------------------------------------------------------------------- 1 |

Palindrome Result

2 | 3 | <% if @phrase.palindrome? %> 4 |
5 |

"<%= @phrase %>" is a palindrome!

6 |
7 | <% else %> 8 |
9 |

"<%= @phrase %>" isn't a palindrome!

10 |
11 | <% end %> 12 | 13 |

Try another one!

14 | 15 |
16 | 17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /Listing_11.57.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 6 tests, 16 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.58.rhtml: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | -------------------------------------------------------------------------------- /Listing_11.59.rhtml: -------------------------------------------------------------------------------- 1 |

Palindrome Result

2 | 3 | <% if @phrase.palindrome? %> 4 |
5 |

"<%= @phrase %>" is a palindrome!

6 |
7 | <% else %> 8 |
9 |

"<%= @phrase %>" isn't a palindrome!

10 |
11 | <% end %> 12 | 13 |

Try another one!

14 | 15 | <%= erb :palindrome_form %> 16 | -------------------------------------------------------------------------------- /Listing_11.6.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | erb :index 5 | end 6 | 7 | get '/about' do 8 | erb :about 9 | end 10 | 11 | get '/palindrome' do 12 | erb :palindrome 13 | end 14 | -------------------------------------------------------------------------------- /Listing_11.60.rhtml: -------------------------------------------------------------------------------- 1 |

Palindrome Detector

2 | 3 | <%= erb :palindrome_form %> 4 | -------------------------------------------------------------------------------- /Listing_11.61.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 6 tests, 16 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_11.7.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | 17 |

Sample Sinatra App

18 | 19 |

20 | This is the sample Sinatra app for 21 | Learn Enough Ruby 22 | to Be Dangerous. Learn more on the About page. 23 |

24 | 25 |

26 | Click the Sator 27 | Square below to run the custom Palindrome 28 | Detector. 29 |

30 | 31 | 32 | Sator Square 33 | 34 |
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /Listing_11.8.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | 17 |

About

18 | 19 |

20 | This site is the final application in 21 | Learn Enough Ruby 22 | to Be Dangerous 23 | by Michael Hartl, 24 | a tutorial introduction to the 25 | Ruby programming language that 26 | is part of 27 | LearnEnough.com. 28 |

29 | 30 |

31 | Learn Enough Ruby to Be Dangerous is a natural prerequisite to 32 | the Ruby on Rails 33 | Tutorial, a book and video series that is one of the leading 34 | introductions to web development. Learn Enough Ruby is also an 35 | excellent choice after the Rails Tutorial for those who 36 | prefer to start with the latter first. 37 |

38 | 39 |
40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /Listing_11.9.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Enough Ruby Sample App 6 | 7 | 9 | 10 | 11 | 14 |
15 |
16 | 17 |

Palindrome Detector

18 | 19 |

This will be the palindrome detector.

20 | 21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /Listing_2.1.txt: -------------------------------------------------------------------------------- 1 | $ ruby -v 2 | ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux] 3 | -------------------------------------------------------------------------------- /Listing_2.10.txt: -------------------------------------------------------------------------------- 1 | $ source <(curl -sL https://cdn.learnenough.com/heroku_install) 2 | -------------------------------------------------------------------------------- /Listing_2.11.txt: -------------------------------------------------------------------------------- 1 | $ heroku create 2 | Creating app... done, ⬢ damp-depths-3 3 | https://damp-depths-3.herokuapp.com/ | https://git.heroku.com/damp-depths-3.git 4 | -------------------------------------------------------------------------------- /Listing_2.12.rb: -------------------------------------------------------------------------------- 1 | require './hello_app' 2 | run Sinatra::Application 3 | -------------------------------------------------------------------------------- /Listing_2.13.rb: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '3.1.1' # Change this line if you're using a different Ruby version. 4 | 5 | gem 'sinatra', '2.2.0' 6 | gem 'puma', '5.6.2' 7 | -------------------------------------------------------------------------------- /Listing_2.2.irb: -------------------------------------------------------------------------------- 1 | $ irb 2 | >> 3 | -------------------------------------------------------------------------------- /Listing_2.3.rb: -------------------------------------------------------------------------------- 1 | IRB.conf[:PROMPT_MODE] = :SIMPLE 2 | IRB.conf[:AUTO_INDENT_MODE] = false 3 | -------------------------------------------------------------------------------- /Listing_2.4.irb: -------------------------------------------------------------------------------- 1 | >> puts "hello, world!" 2 | hello, world! 3 | => nil 4 | -------------------------------------------------------------------------------- /Listing_2.5.rb: -------------------------------------------------------------------------------- 1 | puts "hello, world!" 2 | -------------------------------------------------------------------------------- /Listing_2.6.rb: -------------------------------------------------------------------------------- 1 | puts "hello, world!", "how's it going?" 2 | -------------------------------------------------------------------------------- /Listing_2.7.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | puts "hello, world!" 4 | -------------------------------------------------------------------------------- /Listing_2.8.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | 'hello, world!' 5 | end 6 | -------------------------------------------------------------------------------- /Listing_2.9.txt: -------------------------------------------------------------------------------- 1 | $ ruby hello_app.rb 2 | == Sinatra (v2.0.3) has taken the stage on 4567 for development with 3 | backup from Thin 4 | Thin web server (v1.7.2 codename Bachmanity) 5 | Maximum connections set to 1024 6 | Listening on localhost:4567, CTRL+C to stop 7 | -------------------------------------------------------------------------------- /Listing_3.1.irb: -------------------------------------------------------------------------------- 1 | >> puts "hello\tgoodbye" 2 | >> puts "hello\ngoodbye" 3 | >> puts 'hello\tgoodbye' 4 | >> puts 'hello\ngoodbye' 5 | -------------------------------------------------------------------------------- /Listing_3.10.irb: -------------------------------------------------------------------------------- 1 | >> x = "foo" 2 | >> y = "" 3 | >> if x.length == 0 && y.length == 0 4 | >> "Both strings are empty!" 5 | >> else 6 | >> "At least one of the strings is nonempty." 7 | >> end 8 | => "At least one of the strings is nonempty." 9 | -------------------------------------------------------------------------------- /Listing_3.11.irb: -------------------------------------------------------------------------------- 1 | >> true || false 2 | => true 3 | >> false || true 4 | => true 5 | >> true || true 6 | => true 7 | >> false || false 8 | => false 9 | -------------------------------------------------------------------------------- /Listing_3.12.irb: -------------------------------------------------------------------------------- 1 | >> if x.length == 0 || y.length == 0 2 | >> "At least one of the strings is empty!" 3 | >> else 4 | >> "Neither of the strings is empty." 5 | >> end 6 | => "At least one of the strings is empty!" 7 | -------------------------------------------------------------------------------- /Listing_3.13.irb: -------------------------------------------------------------------------------- 1 | >> !true 2 | => false 3 | >> !false 4 | => true 5 | -------------------------------------------------------------------------------- /Listing_3.14.irb: -------------------------------------------------------------------------------- 1 | >> if !(x.length == 0) 2 | >> "x is not empty." 3 | >> else 4 | >> "x is empty." 5 | >> end 6 | => "x is not empty." 7 | -------------------------------------------------------------------------------- /Listing_3.15.irb: -------------------------------------------------------------------------------- 1 | >> if x.empty? && y.empty? 2 | >> "Both strings are empty!" 3 | >> else 4 | >> "At least one of the strings is nonempty." 5 | >> end 6 | => "At least one of the strings is nonempty." 7 | -------------------------------------------------------------------------------- /Listing_3.16.irb: -------------------------------------------------------------------------------- 1 | >> soliloquy = "To be, or not to be, that is the question:" 2 | >> soliloquy.include?("To be") # Does it include the substring "To be"? 3 | => true 4 | >> soliloquy.include?("question") # What about "question"? 5 | => true 6 | >> soliloquy.include?("nonexistent") # This string doesn't appear. 7 | => false 8 | >> soliloquy.include?("TO BE") # String inclusion is case-sensitive. 9 | => false 10 | -------------------------------------------------------------------------------- /Listing_3.17.irb: -------------------------------------------------------------------------------- 1 | >> puts soliloquy # Just a reminder of what the string is 2 | To be, or not to be, that is the question: 3 | >> soliloquy[0] 4 | => "T" 5 | >> soliloquy[1] 6 | => "o" 7 | >> soliloquy[2] 8 | => " " 9 | -------------------------------------------------------------------------------- /Listing_3.18.irb: -------------------------------------------------------------------------------- 1 | >> for i in 0..4 2 | ?> puts i 3 | >> end 4 | 0 5 | 1 6 | 2 7 | 3 8 | 4 9 | -------------------------------------------------------------------------------- /Listing_3.19.js: -------------------------------------------------------------------------------- 1 | > for (i = 0; i < 5; i++) { 2 | console.log(i); 3 | } 4 | 0 5 | 1 6 | 2 7 | 3 8 | 4 9 | -------------------------------------------------------------------------------- /Listing_3.2.irb: -------------------------------------------------------------------------------- 1 | >> first_name = "Michael" 2 | >> last_name = "Hartl" 3 | -------------------------------------------------------------------------------- /Listing_3.20.irb: -------------------------------------------------------------------------------- 1 | >> for i in 0..(soliloquy.length - 1) 2 | ?> puts soliloquy[i] 3 | >> end 4 | T 5 | o 6 | 7 | b 8 | e 9 | . 10 | . 11 | . 12 | t 13 | i 14 | o 15 | n 16 | : 17 | -------------------------------------------------------------------------------- /Listing_3.3.irb: -------------------------------------------------------------------------------- 1 | >> first_name + " " + last_name 2 | => "Michael Hartl" 3 | -------------------------------------------------------------------------------- /Listing_3.4.irb: -------------------------------------------------------------------------------- 1 | >> first_name + " " + last_name # Concatenation, with a space in between 2 | => "Michael Hartl" 3 | >> "#{first_name} #{last_name}" # The equivalent interpolation 4 | => "Michael Hartl" 5 | -------------------------------------------------------------------------------- /Listing_3.5.irb: -------------------------------------------------------------------------------- 1 | >> password = "foo" 2 | => "foo" 3 | >> if (password.length < 6) 4 | >> "Password is too short." 5 | >> end 6 | => "Password is too short." 7 | -------------------------------------------------------------------------------- /Listing_3.6.irb: -------------------------------------------------------------------------------- 1 | >> if password.length < 6 2 | >> "Password is too short." 3 | >> end 4 | => "Password is too short." 5 | -------------------------------------------------------------------------------- /Listing_3.7.irb: -------------------------------------------------------------------------------- 1 | >> password = "foobar" 2 | >> if password.length < 6 3 | >> "Password is too short." 4 | >> else 5 | >> "Password is long enough." 6 | >> end 7 | => "Password is long enough." 8 | -------------------------------------------------------------------------------- /Listing_3.8.irb: -------------------------------------------------------------------------------- 1 | >> password = "goldilocks" 2 | >> if password.length < 6 3 | >> "Password is too short." 4 | >> elsif password.length < 50 5 | >> "Password is just right!" 6 | >> else 7 | >> "Password is too long." 8 | >> end 9 | => "Password is just right!" 10 | -------------------------------------------------------------------------------- /Listing_3.9.irb: -------------------------------------------------------------------------------- 1 | >> true && false 2 | => false 3 | >> false && true 4 | => false 5 | >> false && false 6 | => false 7 | >> true && true 8 | => true 9 | -------------------------------------------------------------------------------- /Listing_4.1.irb: -------------------------------------------------------------------------------- 1 | >> a[0] 2 | => "b" 3 | >> a[1] 4 | => "a" 5 | >> a[2] 6 | => "d" 7 | -------------------------------------------------------------------------------- /Listing_4.2.irb: -------------------------------------------------------------------------------- 1 | >> a = ["ant", "bat", "cat", 42] 2 | => ["ant", "bat", "cat", 42] 3 | >> a.join # Join on default (empty space). 4 | => "antbatcat42" 5 | >> a.join(", ") # Join on comma-space. 6 | => "ant, bat, cat, 42" 7 | >> a.join(" -- ") # Join on double dashes. 8 | => "ant -- bat -- cat -- 42" 9 | -------------------------------------------------------------------------------- /Listing_4.3.irb: -------------------------------------------------------------------------------- 1 | >> for i in 0..(a.length - 1) 2 | ?> puts a[i] 3 | >> end 4 | ant 5 | bat 6 | cat 7 | 42 8 | -------------------------------------------------------------------------------- /Listing_4.4.irb: -------------------------------------------------------------------------------- 1 | >> a.each do |element| 2 | ?> puts element 3 | >> end 4 | ant 5 | bat 6 | cat 7 | 42 8 | -------------------------------------------------------------------------------- /Listing_5.1.irb: -------------------------------------------------------------------------------- 1 | >> tau = 2 * Math::PI 2 | >> tau.to_s 3 | => "6.283185307179586" 4 | -------------------------------------------------------------------------------- /Listing_5.2.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | DAYNAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", 5 | "Thursday", "Friday", "Saturday"] 6 | dayname = DAYNAMES[Time.now.wday] 7 | "Hello, world! Happy #{dayname}." 8 | end 9 | -------------------------------------------------------------------------------- /Listing_5.3.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | DAYNAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", 4 | "Thursday", "Friday", "Saturday"] 5 | 6 | get '/' do 7 | dayname = DAYNAMES[Time.now.wday] 8 | "Hello, world! Happy #{dayname}." 9 | end 10 | -------------------------------------------------------------------------------- /Listing_5.4.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | dayname = Date::DAYNAMES[Time.now.wday] 5 | "Hello, world! Happy #{dayname}." 6 | end 7 | -------------------------------------------------------------------------------- /Listing_5.5.rb: -------------------------------------------------------------------------------- 1 | sonnet = "Let me not to the marriage of true minds 2 | Admit impediments. Love is not love 3 | Which alters when it alteration finds, 4 | Or bends with the remover to remove. 5 | O no, it is an ever-fixed mark 6 | That looks on tempests and is never shaken 7 | It is the star to every wand'ring bark, 8 | Whose worth's unknown, although his height be taken. 9 | Love's not time's fool, though rosy lips and cheeks 10 | Within his bending sickle's compass come: 11 | Love alters not with his brief hours and weeks, 12 | But bears it out even to the edge of doom. 13 |   If this be error and upon me proved, 14 |   I never writ, nor no man ever loved." 15 | -------------------------------------------------------------------------------- /Listing_5.6.irb: -------------------------------------------------------------------------------- 1 | >> params = {} # Define a hash called 'params' (short for 'parameters'). 2 | => {} 3 | >> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" } 4 | => {:name=>"Michael Hartl", :email=>"mhartl@example.com"} 5 | >> params 6 | => {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}} 7 | >> params[:user][:email] 8 | => "mhartl@example.com" 9 | -------------------------------------------------------------------------------- /Listing_5.7.rb: -------------------------------------------------------------------------------- 1 | sonnet = "Let me not to the marriage of true minds 2 | Admit impediments. Love is not love 3 | Which alters when it alteration finds, 4 | Or bends with the remover to remove. 5 | O no, it is an ever-fixed mark 6 | That looks on tempests and is never shaken 7 | It is the star to every wand'ring bark, 8 | Whose worth's unknown, although his height be taken. 9 | Love's not time's fool, though rosy lips and cheeks 10 | Within his bending sickle's compass come: 11 | Love alters not with his brief hours and weeks, 12 | But bears it out even to the edge of doom. 13 |   If this be error and upon me proved, 14 |   I never writ, nor no man ever loved." 15 | -------------------------------------------------------------------------------- /Listing_5.8.rb: -------------------------------------------------------------------------------- 1 | sonnet = "Let me not to the marriage of true minds 2 | Admit impediments. Love is not love 3 | Which alters when it alteration finds, 4 | Or bends with the remover to remove. 5 | O no, it is an ever-fixed mark 6 | That looks on tempests and is never shaken 7 | It is the star to every wand'ring bark, 8 | Whose worth's unknown, although his height be taken. 9 | Love's not time's fool, though rosy lips and cheeks 10 | Within his bending sickle's compass come: 11 | Love alters not with his brief hours and weeks, 12 | But bears it out even to the edge of doom. 13 |   If this be error and upon me proved, 14 |   I never writ, nor no man ever loved." 15 | 16 | uniques = {} 17 | words = sonnet.scan(/\w+/) 18 | -------------------------------------------------------------------------------- /Listing_5.9.rb: -------------------------------------------------------------------------------- 1 | sonnet = "Let me not to the marriage of true minds 2 | Admit impediments. Love is not love 3 | Which alters when it alteration finds, 4 | Or bends with the remover to remove. 5 | O no, it is an ever-fixed mark 6 | That looks on tempests and is never shaken 7 | It is the star to every wand'ring bark, 8 | Whose worth's unknown, although his height be taken. 9 | Love's not time's fool, though rosy lips and cheeks 10 | Within his bending sickle's compass come: 11 | Love alters not with his brief hours and weeks, 12 | But bears it out even to the edge of doom. 13 |   If this be error and upon me proved, 14 |   I never writ, nor no man ever loved." 15 | 16 | # Unique words 17 | uniques = {} 18 | # All words in the text 19 | words = sonnet.scan(/\w+/) 20 | 21 | # Iterate through `words` and build up a hash of unique words. 22 | words.each do |word| 23 | if uniques[word] 24 | uniques[word] += 1 25 | else 26 | uniques[word] = 1 27 | end 28 | end 29 | 30 | puts uniques 31 | -------------------------------------------------------------------------------- /Listing_6.1.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | DAYNAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", 5 | "Thursday", "Friday", "Saturday"] 6 | dayname = DAYNAMES[Time.now.wday] 7 | "Hello, world! Happy #{dayname}." 8 | end 9 | -------------------------------------------------------------------------------- /Listing_6.10.rb: -------------------------------------------------------------------------------- 1 | # Returns true for a palindrome, false otherwise. 2 | def palindrome?(string) 3 | string.downcase == string.downcase.reverse 4 | end 5 | -------------------------------------------------------------------------------- /Listing_6.11.rb: -------------------------------------------------------------------------------- 1 | # Returns true for a palindrome, false otherwise. 2 | def palindrome?(string) 3 | processed_content = string.downcase 4 | processed_content == processed_content.reverse 5 | end 6 | -------------------------------------------------------------------------------- /Listing_6.12.irb: -------------------------------------------------------------------------------- 1 | >> def email_parts(email) 2 | ?> # FILL IN 3 | >> end 4 | -------------------------------------------------------------------------------- /Listing_6.13.js: -------------------------------------------------------------------------------- 1 | > ["ant", "bat", "cat", 42].forEach(function(element) { 2 | console.log(element); 3 | }); 4 | ant 5 | bat 6 | cat 7 | 42 8 | -------------------------------------------------------------------------------- /Listing_6.14.irb: -------------------------------------------------------------------------------- 1 | >> ["ant", "bat", "cat", 42].each do |element| 2 | ?> puts element 3 | >> end 4 | ant 5 | bat 6 | cat 7 | 42 8 | -------------------------------------------------------------------------------- /Listing_6.15.rb: -------------------------------------------------------------------------------- 1 | def sandwich 2 | puts "top bread" 3 | yield 4 | puts "bottom bread" 5 | end 6 | -------------------------------------------------------------------------------- /Listing_6.16.rb: -------------------------------------------------------------------------------- 1 | def sandwich 2 | puts "top bread" 3 | yield 4 | puts "bottom bread" 5 | end 6 | 7 | sandwich do 8 | puts "mutton, lettuce, and tomato" 9 | end 10 | -------------------------------------------------------------------------------- /Listing_6.17.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | def tag(tagname, text) 5 | html = "<#{tagname}>#{text}" 6 | yield html 7 | end 8 | -------------------------------------------------------------------------------- /Listing_6.18.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | def tag(tagname, text) 5 | html = "<#{tagname}>#{text}" 6 | yield html 7 | end 8 | 9 | # Wrap some text in a paragraph tag. 10 | tag("p", "Lorem ipsum dolor sit amet") do |markup| 11 | puts markup 12 | end 13 | -------------------------------------------------------------------------------- /Listing_6.19.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | def bad_sandwich(contents) 5 | puts "top bread" 6 | contents 7 | puts "bottom bread" 8 | end 9 | 10 | bad_sandwich(puts "mutton, lettuce, and tomato") 11 | -------------------------------------------------------------------------------- /Listing_6.2.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | # Returns the day of the week for the given Time object. 4 | def day_of_the_week(time) 5 | Date::DAYNAMES[time.wday] 6 | end 7 | 8 | get '/' do 9 | DAYNAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", 10 | "Thursday", "Friday", "Saturday"] 11 | dayname = DAYNAMES[Time.now.wday] 12 | "Hello, world! Happy #{dayname}." 13 | end 14 | -------------------------------------------------------------------------------- /Listing_6.3.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | # Returns the day of the week for the given Time object. 4 | def day_of_the_week(time) 5 | Date::DAYNAMES[time.wday] 6 | end 7 | 8 | get '/' do 9 | "Hello, world! Happy #{day_of_the_week(Time.now)}." 10 | end 11 | -------------------------------------------------------------------------------- /Listing_6.4.rb: -------------------------------------------------------------------------------- 1 | require 'date' 2 | 3 | # Returns the day of the week for the given Time object. 4 | def day_of_the_week(time) 5 | Date::DAYNAMES[time.wday] 6 | end 7 | -------------------------------------------------------------------------------- /Listing_6.5.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | get '/' do 4 | "Hello, world! Happy #{day_of_the_week(Time.now)}—now from a file!" 5 | end 6 | -------------------------------------------------------------------------------- /Listing_6.6.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | require './day' 3 | 4 | get '/' do 5 | "Hello, world! Happy #{day_of_the_week(Time.now)}—now from a file!" 6 | end 7 | -------------------------------------------------------------------------------- /Listing_6.7.rb: -------------------------------------------------------------------------------- 1 | require 'date' 2 | 3 | # Returns the day of the week for the given Time object. 4 | def day_of_the_week(time) 5 | Date::DAYNAMES[time.wday] 6 | end 7 | 8 | # Returns a friendly greeting. 9 | def greeting(time) 10 | # FILL IN 11 | end 12 | -------------------------------------------------------------------------------- /Listing_6.8.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | require './day' 3 | 4 | get '/' do 5 | greeting(Time.now) 6 | end 7 | -------------------------------------------------------------------------------- /Listing_6.9.rb: -------------------------------------------------------------------------------- 1 | # Returns true for a palindrome, false otherwise. 2 | def palindrome?(string) 3 | string == string.reverse 4 | end 5 | -------------------------------------------------------------------------------- /Listing_7.1.rb: -------------------------------------------------------------------------------- 1 | states_map = ["Kansas", "Nebraska", "North Dakota", "South Dakota"] 2 | 3 | # urls: Imperative version 4 | def imperative_urls(states) 5 | urls = [] 6 | states.each do |state| 7 | urls << state.downcase.split.join("-") 8 | end 9 | urls 10 | end 11 | p imperative_urls(states) 12 | -------------------------------------------------------------------------------- /Listing_7.10.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | # lengths: Functional version using `inject` 5 | def functional_lengths(states) 6 | states.inject({}) do |lengths, state| 7 | lengths[state] = state.length 8 | lengths 9 | end 10 | end 11 | puts functional_lengths(states) 12 | -------------------------------------------------------------------------------- /Listing_7.2.rb: -------------------------------------------------------------------------------- 1 | states = ["Kansas", "Nebraska", "North Dakota", "South Dakota"] 2 | 3 | # urls: Imperative version 4 | def imperative_urls(states) 5 | urls = [] 6 | states.each do |state| 7 | urls << state.downcase.split.join("-") 8 | end 9 | urls 10 | end 11 | p imperative_urls(states) 12 | 13 | # urls: Functional version 14 | def functional_urls(states) 15 | states.map { |state| state.downcase.split.join('-') } 16 | end 17 | puts functional_urls(states).inspect 18 | -------------------------------------------------------------------------------- /Listing_7.3.rb: -------------------------------------------------------------------------------- 1 | states = ["Kansas", "Nebraska", "North Dakota", "South Dakota"] 2 | 3 | # Returns a URL-friendly version of a string. 4 | # Example: "North Dakota" -> "north-dakota" 5 | def urlify(string) 6 | string.downcase.split.join('-') 7 | end 8 | 9 | # urls: Imperative version 10 | def imperative_urls(states) 11 | urls = [] 12 | states.each do |state| 13 | urls << urlify(state) 14 | end 15 | urls 16 | end 17 | puts imperative_urls(states).inspect 18 | 19 | # urls: Functional version 20 | def functional_urls(states) 21 | states.map { |state| urlify(state) } 22 | end 23 | puts functional_urls(states).inspect 24 | -------------------------------------------------------------------------------- /Listing_7.4.rb: -------------------------------------------------------------------------------- 1 | states = ["Kansas", "Nebraska", "North Dakota", "South Dakota"] 2 | . 3 | . 4 | . 5 | # singles: Imperative version 6 | def imperative_singles(states) 7 | singles = [] 8 | states.each do |state| 9 | if state.split.length == 1 10 | singles << state 11 | end 12 | end 13 | singles 14 | end 15 | puts imperative_singles(states).inspect 16 | -------------------------------------------------------------------------------- /Listing_7.5.rb: -------------------------------------------------------------------------------- 1 | states = ["Kansas", "Nebraska", "North Dakota", "South Dakota"] 2 | . 3 | . 4 | . 5 | # singles: Imperative version 6 | def imperative_singles(states) 7 | singles = [] 8 | states.each do |state| 9 | if (state.split.length == 1) 10 | singles << state 11 | end 12 | end 13 | singles 14 | end 15 | puts imperative_singles(states).inspect 16 | 17 | # singles: Functional version 18 | def functional_singles(states) 19 | states.select { |state| state.split.length == 1 } 20 | end 21 | puts functional_singles(states).inspect 22 | -------------------------------------------------------------------------------- /Listing_7.6.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | numbers = 1..10 5 | 6 | # sum: Imperative solution 7 | def imperative_sum(numbers) 8 | total = 0 9 | numbers.each do |n| 10 | total += n 11 | end 12 | total 13 | end 14 | puts imperative_sum(numbers) 15 | -------------------------------------------------------------------------------- /Listing_7.7.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | numbers = 1..10 5 | 6 | # sum: Imperative solution 7 | def imperative_sum(numbers) 8 | total = 0 9 | numbers.each do |n| 10 | total += n 11 | end 12 | total 13 | end 14 | puts imperative_sum(numbers) 15 | 16 | # sum: Functional solution 17 | def functional_sum(numbers) 18 | numbers.reduce { |total, n| total + n } 19 | end 20 | puts functional_sum(numbers) 21 | -------------------------------------------------------------------------------- /Listing_7.8.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | # lengths: Imperative version 5 | def imperative_lengths(states) 6 | lengths = {} 7 | states.each do |state| 8 | lengths[state] = state.length 9 | end 10 | lengths 11 | end 12 | puts imperative_lengths(states) 13 | -------------------------------------------------------------------------------- /Listing_7.9.rb: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | # lengths: Imperative version 5 | def imperative_lengths(states) 6 | lengths = {} 7 | states.each do |state| 8 | lengths[state] = state.length 9 | end 10 | lengths 11 | end 12 | puts imperative_lengths(states) 13 | 14 | # lengths: Functional version 15 | def functional_lengths(states) 16 | states.reduce({}) do |lengths, state| 17 | lengths[state] = state.length 18 | lengths 19 | end 20 | end 21 | puts functional_lengths(states) 22 | -------------------------------------------------------------------------------- /Listing_8.1.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase 3 | end 4 | 5 | phrase = Phrase.new 6 | puts phrase 7 | -------------------------------------------------------------------------------- /Listing_8.10.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class (inheriting from String). 2 | class Phrase < String 3 | 4 | # Returns true for a palindrome, false otherwise. 5 | def palindrome? 6 | processed_content = self.downcase 7 | processed_content == processed_content.reverse 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Listing_8.11.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class (inheriting from String). 2 | class Phrase < String 3 | 4 | # Returns true for a palindrome, false otherwise. 5 | def palindrome? 6 | processed_content = downcase 7 | processed_content == processed_content.reverse 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Listing_8.12.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class (inheriting from String). 2 | class Phrase < String 3 | 4 | # Returns content for palindrome testing. 5 | def processed_content 6 | self.downcase 7 | end 8 | 9 | # Returns true for a palindrome, false otherwise. 10 | def palindrome? 11 | processed_content == processed_content.reverse 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /Listing_8.13.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class (inheriting from String). 2 | class Phrase < String 3 | . 4 | . 5 | . 6 | end 7 | 8 | # Defines a translated Phrase. 9 | class TranslatedPhrase < Phrase 10 | attr_accessor :translation 11 | 12 | def initialize(content, translation) 13 | super(content) 14 | @translation = translation 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /Listing_8.14.irb: -------------------------------------------------------------------------------- 1 | >> load "./palindrome.rb" 2 | >> frase = TranslatedPhrase.new("recognize", "reconocer") 3 | >> frase.palindrome? 4 | => false 5 | -------------------------------------------------------------------------------- /Listing_8.15.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class (inheriting from String). 2 | class Phrase < String 3 | 4 | # Returns content for palindrome testing. 5 | def processed_content 6 | self.downcase 7 | end 8 | 9 | # Returns true for a palindrome, false otherwise. 10 | def palindrome? 11 | processed_content == processed_content.reverse 12 | end 13 | end 14 | 15 | # Defines a translated Phrase. 16 | class TranslatedPhrase < Phrase 17 | attr_accessor :translation 18 | 19 | def initialize(content, translation) 20 | super(content) 21 | @translation = translation 22 | end 23 | 24 | # Processes the translation for palindrome testing. 25 | def processed_content 26 | self.translation.downcase 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /Listing_8.16.irb: -------------------------------------------------------------------------------- 1 | >> load "./palindrome.rb" 2 | >> frase = TranslatedPhrase.new("recognize", "reconocer") 3 | >> frase.palindrome? 4 | => true 5 | -------------------------------------------------------------------------------- /Listing_8.17.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class (inheriting from String). 2 | class Phrase < String 3 | 4 | # Processes the string for palindrome testing. 5 | def processor(string) 6 | # FILL IN 7 | end 8 | 9 | # Returns content for palindrome testing. 10 | def processed_content 11 | processor(self) 12 | end 13 | 14 | # Returns true for a palindrome, false otherwise. 15 | def palindrome? 16 | processed_content == processed_content.reverse 17 | end 18 | end 19 | 20 | # Defines a translated Phrase. 21 | class TranslatedPhrase < Phrase 22 | attr_accessor :translation 23 | 24 | def initialize(content, translation) 25 | super(content) 26 | @translation = translation 27 | end 28 | 29 | # Processes the translation for palindrome testing. 30 | def processed_content 31 | processor(translation) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /Listing_8.18.rb: -------------------------------------------------------------------------------- 1 | class Phrase < String 2 | 3 | # Returns content for palindrome testing. 4 | def processed_content 5 | self.downcase 6 | end 7 | 8 | # Returns true for a palindrome, false otherwise. 9 | def palindrome? 10 | processed_content == processed_content.reverse 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Listing_8.19.rb: -------------------------------------------------------------------------------- 1 | class String 2 | 3 | # Returns content for palindrome testing. 4 | def processed_content 5 | self.downcase 6 | end 7 | 8 | # Returns true for a palindrome, false otherwise. 9 | def palindrome? 10 | processed_content == processed_content.reverse 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Listing_8.2.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase 3 | 4 | def initialize(content) 5 | @content = content 6 | end 7 | end 8 | 9 | phrase = Phrase.new("Madam, I'm Adam.") 10 | puts phrase.content 11 | -------------------------------------------------------------------------------- /Listing_8.20.rb: -------------------------------------------------------------------------------- 1 | class String 2 | 3 | # Returns true for a palindrome, false otherwise. 4 | def palindrome? 5 | processed_content == processed_content.reverse 6 | end 7 | 8 | private 9 | 10 | # Returns content for palindrome testing. 11 | def processed_content 12 | self.downcase 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_8.21.rb: -------------------------------------------------------------------------------- 1 | class String 2 | 3 | # Returns true for a palindrome, false otherwise. 4 | def palindrome? 5 | processed_content == processed_content.reverse 6 | end 7 | 8 | private 9 | 10 | # Returns content for palindrome testing. 11 | def processed_content 12 | self.downcase 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_8.22.rb: -------------------------------------------------------------------------------- 1 | class Integer 2 | 3 | # Returns true for a palindrome, false otherwise. 4 | def palindrome? 5 | processed_content == processed_content.reverse 6 | end 7 | 8 | private 9 | 10 | # Returns content for palindrome testing. 11 | def processed_content 12 | self.to_s 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_8.23.rb: -------------------------------------------------------------------------------- 1 | module Palindrome 2 | 3 | # Returns true for a palindrome, false otherwise. 4 | def palindrome? 5 | processed_content == processed_content.reverse 6 | end 7 | 8 | private 9 | 10 | # Returns content for palindrome testing. 11 | def processed_content 12 | self.to_s.downcase 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_8.24.rb: -------------------------------------------------------------------------------- 1 | module Palindrome 2 | 3 | # Returns true for a palindrome, false otherwise. 4 | def palindrome? 5 | processed_content == processed_content.reverse 6 | end 7 | 8 | private 9 | 10 | # Returns content for palindrome testing. 11 | def processed_content 12 | self.to_s.downcase 13 | end 14 | end 15 | 16 | class String 17 | include Palindrome 18 | end 19 | 20 | class Integer 21 | include Palindrome 22 | end 23 | -------------------------------------------------------------------------------- /Listing_8.3.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase 3 | attr_accessor :content 4 | 5 | def initialize(content) 6 | @content = content 7 | end 8 | end 9 | 10 | phrase = Phrase.new("Madam, I'm Adam.") 11 | puts phrase.content 12 | -------------------------------------------------------------------------------- /Listing_8.4.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase 3 | attr_accessor :content 4 | 5 | def initialize(content) 6 | @content = content 7 | end 8 | end 9 | 10 | phrase = Phrase.new("Madam, I'm Adam.") 11 | puts phrase.content 12 | 13 | phrase.content = "Able was I, ere I saw Elba." 14 | puts phrase.content 15 | -------------------------------------------------------------------------------- /Listing_8.5.rb: -------------------------------------------------------------------------------- 1 | # Returns true for a palindrome, false otherwise. 2 | def palindrome?(string) 3 | processed_content = string.downcase 4 | processed_content == processed_content.reverse 5 | end 6 | 7 | # Defines a Phrase class. 8 | class Phrase 9 | attr_accessor :content 10 | 11 | def initialize(content) 12 | @content = content 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_8.6.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase 3 | attr_accessor :content 4 | 5 | def initialize(content) 6 | @content = content 7 | end 8 | 9 | # Returns true for a palindrome, false otherwise. 10 | def palindrome? 11 | processed_content = self.content.downcase 12 | processed_content == processed_content.reverse 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_8.7.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase 3 | attr_accessor :content 4 | 5 | def initialize(content) 6 | @content = content 7 | end 8 | 9 | # Returns true for a palindrome, false otherwise. 10 | def palindrome? 11 | processed_content = self.content.downcase 12 | processed_content == processed_content.reverse 13 | end 14 | 15 | # Makes the phrase LOUDER. 16 | def louder 17 | # FILL IN 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /Listing_8.8.irb: -------------------------------------------------------------------------------- 1 | >> load "./palindrome.rb" 2 | >> p = Phrase.new("yo adrian!") 3 | >> p.louder 4 | => "YO ADRIAN!" 5 | -------------------------------------------------------------------------------- /Listing_8.9.rb: -------------------------------------------------------------------------------- 1 | # Defines a Phrase class. 2 | class Phrase < String 3 | attr_accessor :content 4 | 5 | def initialize(content) 6 | @content = content 7 | end 8 | 9 | # Returns true for a palindrome, false otherwise. 10 | def palindrome? 11 | processed_content = self.downcase 12 | processed_content == processed_content.reverse 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Listing_9.1.txt: -------------------------------------------------------------------------------- 1 | $ cd ~/repos # Use ~/environment/repos on Cloud9 2 | $ bundle gem _palindrome 3 | Do you want to generate tests with your gem? 4 | Type 'rspec' or 'minitest' to generate those test files now and in the future. 5 | rspec/minitest/(none): minitest 6 | Do you want to license your code permissively under the MIT license? y/(n): n 7 | Do you want to include a code of conduct in gems you generate? y/(n): n 8 | -------------------------------------------------------------------------------- /Listing_9.10.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | module MhartlPalindrome 4 | # Your code goes here... 5 | end 6 | -------------------------------------------------------------------------------- /Listing_9.11.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | private 11 | 12 | # Returns content for palindrome testing. 13 | def processed_content 14 | self.downcase 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /Listing_9.12.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | assert !"apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Listing_9.13.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.14.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | assert !"apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | 13 | def test_mixed_case_palindrome 14 | skip 15 | end 16 | 17 | def test_palindrome_with_punctuation 18 | skip 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /Listing_9.15.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 4 tests, 2 assertions, 0 failures, 0 errors, 2 skips 3 | -------------------------------------------------------------------------------- /Listing_9.16.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | assert !"apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | 13 | def test_mixed_case_palindrome 14 | # FILL IN 15 | end 16 | 17 | def test_palindrome_with_punctuation 18 | skip 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /Listing_9.17.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | private 11 | 12 | # Returns content for palindrome testing. 13 | def processed_content 14 | self 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /Listing_9.18.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | refute "apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | 13 | def test_mixed_case_palindrome 14 | assert "RaceCar".palindrome? 15 | end 16 | 17 | def test_palindrome_with_punctuation 18 | assert "Madam, I'm Adam.".palindrome? 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /Listing_9.19.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 4 tests, 4 assertions, 1 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.2.rb: -------------------------------------------------------------------------------- 1 | lib = File.expand_path("../lib", __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require "mhartl_palindrome/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "mhartl_palindrome" 7 | spec.version = MhartlPalindrome::VERSION 8 | spec.authors = ["Michael Hartl"] 9 | spec.email = ["michael@michaelhartl.com"] 10 | 11 | spec.summary = %q{Palindrome detector} 12 | spec.description = %q{Learn Enough Ruby palindrome detector} 13 | spec.homepage = "https://github.com/mhartl/mhartl_palindrome" 14 | spec.license = "MIT" 15 | 16 | # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 17 | # 'allowed_push_host' 18 | # to allow pushing to a single host or delete this section to allow pushing to 19 | # any host. 20 | if spec.respond_to?(:metadata) 21 | spec.metadata["allowed_push_host"] = "https://rubygems.org/" 22 | else 23 | raise "RubyGems 2.0 or newer is required to protect against " \ 24 | "public gem pushes." 25 | end 26 | 27 | # Specify which files should be added to the gem when it is released. 28 | # The `git ls-files -z` loads the files in the RubyGem 29 | # that have been added into git. 30 | spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do 31 | `git ls-files -z`.split("\x0").reject do 32 | |f| f.match(%r{^(test|spec|features)/}) 33 | end 34 | end 35 | spec.bindir = "exe" 36 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 37 | spec.require_paths = ["lib"] 38 | 39 | spec.add_development_dependency "bundler", "~> 1.16" 40 | spec.add_development_dependency "rake", "~> 10.0" 41 | spec.add_development_dependency "minitest", "~> 5.0" 42 | end 43 | 44 | -------------------------------------------------------------------------------- /Listing_9.20.rb: -------------------------------------------------------------------------------- 1 | assert "Madam, I'm Adam.".letters == "MadamImAdam" 2 | -------------------------------------------------------------------------------- /Listing_9.21.rb: -------------------------------------------------------------------------------- 1 | assert_equal , 2 | -------------------------------------------------------------------------------- /Listing_9.22.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | refute "apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | 13 | def test_mixed_case_palindrome 14 | assert "RaceCar".palindrome? 15 | end 16 | 17 | def test_palindrome_with_punctuation 18 | assert "Madam, I'm Adam.".palindrome? 19 | end 20 | 21 | def test_letters 22 | assert_equal "MadamImAdam", "Madam, I'm Adam.".letters 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /Listing_9.23.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | NoMethodError: undefined method `letters' for "Madam, I'm Adam.":String 3 | 5 tests, 4 assertions, 0 failures, 1 errors, 0 skips 4 | -------------------------------------------------------------------------------- /Listing_9.24.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | # Returns the letters in the string. 11 | def letters 12 | end 13 | 14 | private 15 | 16 | # Returns content for palindrome testing. 17 | def processed_content 18 | self.downcase 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /Listing_9.25.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | FAIL["test_letters", "MhartlPalindromeTest", 0.0007690000347793102] 3 | test_letters#MhartlPalindromeTest (0.00s) 4 | Expected: "MadamImAdam" 5 | Actual: nil 6 | 5 tests, 5 assertions, 2 failures, 0 errors, 0 skips 7 | -------------------------------------------------------------------------------- /Listing_9.26.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | # Returns the letters in the string. 11 | def letters 12 | the_letters = [] 13 | for i in 0..self.length - 1 14 | if self[i].match(/[a-zA-Z]/) 15 | the_letters << self[i] 16 | end 17 | end 18 | the_letters.join 19 | end 20 | 21 | private 22 | 23 | # Returns content for palindrome testing. 24 | def processed_content 25 | self.downcase 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /Listing_9.27.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 5 tests, 5 assertions, 1 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.28.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | # Returns the letters in the string. 11 | def letters 12 | the_letters = [] 13 | for i in 0..self.length - 1 14 | if self[i].match(/[a-zA-Z]/) 15 | the_letters << self[i] 16 | end 17 | end 18 | the_letters.join 19 | end 20 | 21 | private 22 | 23 | # Returns content for palindrome testing. 24 | def processed_content 25 | self.letters.downcase 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /Listing_9.29.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 5 tests, 5 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.3.rb: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } 4 | 5 | # Specify your gem's dependencies in _palindrome.gemspec 6 | gemspec 7 | 8 | gem 'minitest-reporters', '1.2.0' 9 | -------------------------------------------------------------------------------- /Listing_9.30.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | # Returns the letters in the string. 11 | def letters 12 | the_letters = [] 13 | letter_regex = /[a-z]/i 14 | self.chars.each do |character| 15 | if character.match(letter_regex) 16 | the_letters << character 17 | end 18 | end 19 | the_letters.join 20 | end 21 | 22 | private 23 | 24 | # Returns content for palindrome testing. 25 | def processed_content 26 | self.letters.downcase 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /Listing_9.31.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 5 tests, 5 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.32.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | # Returns the letters in the string. 11 | def letters 12 | self.chars.select { |c| c.match(/[a-z]/i) }.join 13 | end 14 | 15 | private 16 | 17 | # Returns content for palindrome testing. 18 | def processed_content 19 | self.letters.downcase 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /Listing_9.33.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 5 tests, 5 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.34.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | refute "apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | 13 | def test_mixed_case_palindrome 14 | assert "RaceCar".palindrome? 15 | end 16 | 17 | def test_palindrome_with_punctuation 18 | assert "Madam, I'm Adam.".palindrome? 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /Listing_9.35.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | private 11 | 12 | # Returns content for palindrome testing. 13 | def processed_content 14 | self.scan(/[a-z]/i).join.downcase 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /Listing_9.36.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | class String 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | private 11 | 12 | # Returns content for palindrome testing. 13 | def processed_content 14 | scan(/[a-z]/i).join.downcase 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /Listing_9.37.text: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 4 tests, 4 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.38.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | module MhartlPalindrome 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | processed_content == processed_content.reverse 8 | end 9 | 10 | private 11 | 12 | # Returns content for palindrome testing. 13 | def processed_content 14 | scan(/[a-z]/i).join.downcase 15 | end 16 | end 17 | 18 | class String 19 | include MhartlPalindrome 20 | end 21 | -------------------------------------------------------------------------------- /Listing_9.39.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | 5 | def test_non_palindrome 6 | refute "apple".palindrome? 7 | end 8 | 9 | def test_literal_palindrome 10 | assert "racecar".palindrome? 11 | end 12 | 13 | def test_mixed_case_palindrome 14 | assert "RaceCar".palindrome? 15 | end 16 | 17 | def test_palindrome_with_punctuation 18 | assert "Madam, I'm Adam.".palindrome? 19 | end 20 | 21 | def test_integer_non_palindrome 22 | FILL_IN 12345.palindrome? 23 | end 24 | 25 | def test_integer_palindrome 26 | FILL_IN 12321.palindrome? 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /Listing_9.4.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) 2 | require "mhartl_palindrome" 3 | require "minitest/autorun" 4 | require "minitest/reporters" 5 | Minitest::Reporters.use! 6 | -------------------------------------------------------------------------------- /Listing_9.40.rb: -------------------------------------------------------------------------------- 1 | require "mhartl_palindrome/version" 2 | 3 | module MhartlPalindrome 4 | 5 | # Returns true for a palindrome, false otherwise. 6 | def palindrome? 7 | if processed_content.empty? 8 | false 9 | else 10 | processed_content == processed_content.reverse 11 | end 12 | end 13 | 14 | private 15 | 16 | # Returns content for palindrome testing. 17 | def processed_content 18 | to_s.scan(/[a-zFILL_IN]/i).join.downcase 19 | end 20 | end 21 | 22 | class String 23 | include MhartlPalindrome 24 | end 25 | 26 | class Integer 27 | include FILL_IN 28 | end 29 | -------------------------------------------------------------------------------- /Listing_9.5.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | Started with run options --seed 57409 3 | 4 | FAIL["test_it_does_something_useful", "MhartlPalindromeTest", 5 | 0.0007609999738633633] 6 | test_it_does_something_useful#MhartlPalindromeTest (0.00s) 7 | Expected false to be truthy. 8 | /Users/mhartl/repos/mhartl_palindrome/test/mhartl_palindrome_test.rb:9:in 9 | `test_it_does_something_useful' 10 | 11 | 2/2: [===================================] 100% Time: 00:00:00, Time: 00:00:00 12 | 13 | Finished in 0.00119s 14 | 2 tests, 2 assertions, 1 failures, 0 errors, 0 skips 15 | -------------------------------------------------------------------------------- /Listing_9.6.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class MhartlPalindromeTest < Minitest::Test 4 | def test_that_it_has_a_version_number 5 | refute_nil ::MhartlPalindrome::VERSION 6 | end 7 | 8 | def test_it_does_something_useful 9 | assert false 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Listing_9.7.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 2 tests, 2 assertions, 1 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /Listing_9.8.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class Mhartl::PalindromeTest < Minitest::Test 4 | def test_that_it_has_a_version_number 5 | refute_nil ::Mhartl::Palindrome::VERSION 6 | end 7 | 8 | def test_it_does_something_useful 9 | assert true 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Listing_9.9.txt: -------------------------------------------------------------------------------- 1 | $ bundle exec rake test 2 | 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LE Ruby Code Listings 2 | 3 | This repository contains files for all the code listings in *Learn Enough Ruby to Be Dangerous* by Michael Hartl. 4 | --------------------------------------------------------------------------------