shimadama
11/19/2013 - 4:30 PM

やわらかRuby

やわらかRuby

やわらかRubyはCC BY 4.0 で提供します。
詳細: https://creativecommons.org/licenses/by/4.0/deed.ja

This work is licensed under a Creative Commons Attribution 4.0 International License.
See also: https://creativecommons.org/licenses/by/4.0/deed

Setup

chapter 0: Ruby をインストールする

  • rbenv
  • ruby-build

問0-1

  • 以下のコマンドの出力結果を確認してみよう
# (1)
rbenv init -
# (2)
which ruby
# (3)
file `which ruby`
# (3')
file /usr/bin/ruby
# (4)
cat `which ruby`

Rubyを遊び尽くす弾丸ツアー

chapter 1: 整数、文字列、配列、ハッシュ

  • 頻出表現
String#to_i
#=Stringクラスのオブジェクトのメソッドto_i
3.odd?
#=> true
4.odd?
#=> false

"paperboy".size
#=> 8
"paperboy".count("p")
#=> 2
"paperboy".reverse
#=> "yobrepap"
[1, 4, 5, 3, 2].sort
#=> [1, 2, 3, 4, 5]

問1-1

  • 次のメソッドは存在する?存在しない?

    1. Array#shuffle # ランダムに並び替える
    1. String#hexadecimal # 16進数として解釈する
    1. Integer#hours # 時間だとして何秒か表示する

chapter 2: ビックリとハテナ

  • ハテナで終わるメソッドはtrueまたはfalseを返す。?で終わることが出来るので、わざわざ is_~ を付けない。
  • ビックリで終わるメソッドは、元のオブジェクトに操作を加える(破壊的メソッド)
    • ただし、破壊的でないメソッドとかならず対になって存在する(Array#concatなどはビックリじゃないけど破壊的)
str = "quail"
str.reverse
#=> "liauq"
str
#=> "quail"
str.reverse!
#=> "liauq"
str
#=> "liauq"

str.start_with? "q"
#=> false

問2-1

  • 以下のstr1とstr2の違いは何?
str1 = str2 = "paperboy"
str1 += "&co." 
str2 << "&co."
# ヒント
str1 == str2 #=> ?
str1.object_id == str2.object_id #=> ?

問2-2

  • こうするとstr1は変更されるが、
str1 = "paperboy"
str1.tr! "p", "q"
  • こうするとstr2は変更されない。String#dupは何をしている?
str2 = "paperboy"
str2.dup.tr! "p", "q"

問2-3

  • 整数のクラス(Integer)に「!」で終わるメソッドはあるか?それはなぜか?

chapter 3: ブロック

  • 3回繰り返す
3.times do
  puts "Hello, world!"
end
  • 配列に対して繰り返す
["dog", "cat", "chicken"].each do |name|
  puts sprintf("%s is an animal", name)
end
  • Fileを読み込んで必ず閉じる
File.open("/etc/hosts") do |f|
  puts f.read
end

問3-1

p = Proc.new do |obj|
  p obj
end
    1. p はどんなオブジェクト?irbで調べてみよう
    1. また、以下を実行するとどう表示される?
["dog", "cat", "chicken"].each &p
["dog", "cat", "chicken"].each p

p.call "dog"

chapter 4: クラスとモジュール

class Animal
  def warm_body?
    false
  end
end

class Fish < Animal
end

class Mammal < Animal
  def warm_body?
    true
  end
end

Fish.new.warm_body?
Mammal.new.warm_body?
  • モジュールと三角継承
class Animal
end
class Mammal < Animal
  def swimmable?
    false
  end
end
module Swimmable
  def swimmable?
    true
  end
end

class Fish < Animal
  include Swimmable
end

class Dolphin < Mammal
  include Swimmable
end

Fish.new.swimmable?
Mammal.new.swimmable?
Dolphin.new.swimmable?
  • モジュールとは何だろう?

    • クラスのメソッド定義の一部を切り出したもの
    • 便利メソッドを束ねたもの
    • 名前空間
  • インスタンス変数

class Dog
  def initialize(name)
    @name = name
  end

  def info
    "This dog's name is #{@name}"
  end
end

dog = Dog.new("Akubi")
puts dog.info

# こうでもいいかも
class Dog
  attr_accessor :name

  def initialize(name)
    self.name = name
  end

  def info
    "This dog's name is #{name}"
  end
end
  • クラスメソッドの定義
class Dog
  class << self
    def print_info(name)
      dog = new(name)
      puts dog.info
    end
  end
end

問4-1

  • 以下のメソッドの結果はどういう意味か?
Dolphin.ancestors

問4-2

    1. Rubyの組み込みクラスの継承関係のドキュメントを探して、確認してみよう
    1. また、Enumerable Comperable を継承しているクラスは何か確認してみよう

chapter 5: オープンクラス

def fizzbuzz(n)
  (1..n).each do |i|
    out = ""
    if (i % 3).zero?
      out = "Fizz"
    end
    if (i % 5).zero?
      out += "Buzz"
    end
    out = i.to_s if out.empty?
    puts out
  end
end
  • 100.to_fizzbuzz って呼び出したくない?
class Integer
  def to_fizzbuzz
    (1..self).each do |i|
      out = ""
     if (i % 3).zero?
        out = "Fizz"
      end
      if (i % 5).zero?
        out += "Buzz"
      end
      out = i.to_s if out.empty?
      puts out
    end
  end
end

200.to_fizzbuzz

問5-1

  • Integer#hours を自作しよう

問5-2

  • エスケープシーケンスについて調べて、 String#to_red を追加しよう

chapter 6: ほんのちょっとだけメタプログラミング

bloc = proc do
  puts reverse
  puts size
  puts chars.shuffle.join
end

bloc.call
#=> NoMethodError!

str = "paperboy"
str.instance_eval &bloc
#=> !!!

問6-1

    1. 実行して、その出力結果を記述しよう
    1. どういうことか考えるだけ考えてみよう

問6-2

  • 以下と比較しよう。 Object#indtance_evalKernel#eval はどう違う?
methods = "chars.shuffle.join"
str = "paperboy"
eval "puts str.#{methods}"

ちょっとだけ実用Ruby

chapter 7: RubyGems

  • Rubyのパッケージマネージャー
  • Rubyの便利プログラムのひとまとまり=gem
$ gem list -rd hashie

*** REMOTE GEMS ***

hashie (2.0.5)
    Authors: Michael Bleigh, Jerry Cheung
    Homepage: https://github.com/intridea/hashie

    Your friendly neighborhood hash toolkit.
  • インストール
$ gem install hashie
  • 使うには
require "hashie"
options = Hashie::Mash.new(name: "Akubi")
options.name
  • gem以外にも、「標準添付ライブラリ」というものもあるよ
require "uri"
URI.parse "https://lolipop.jp"
  • gemの正体
    • 実は、特定の構成のファイル群をgzipで固めただけのもの
    • 一部はビルドスクリプトも付いている
    • インストール時に展開して特定のディレクトリに配置する

問7-1

  • インストールしたgemについて、以下の表示を確認しよう
$ gem list -d hashie

問7-2

  • RubyGems.org で適当なgemをダウンロードして、展開して中身を見てみよう

chapter 8: Bundler

  • 「プロジェクトでどんなgemを使うか」を管理するためのライブラリ
  • もともとRailsのgem管理システムが進化したもの
source "https://rubygems.org"

gem "hashie"
gem "coderay"
gem "redcarpet"
## brew install libxml2 libxslt
$ cat Gemfile
$ bundle install
require "bundler/setup"
Bundler.require
# sample use coderay
puts CodeRay.scan(<<EOC, :ruby).terminal
def add(some)
  1 + 2 + some
end
EOC
$ bundle exec ruby sample.rb

問8-1

  • Gemfile.lock の中身を見てみよう

問8-2

  • Gemfileのgem "redcarpet" をコメントアウトしたりしなかったりした状態で、以下のスクリプトの実行結果を見てみよう
    • ヒント: スクリプトは、Gemfileと同じディレクトリに配置しないとうまく行かないかも
require "bundler/setup"
require "redcarpet"
p defined?(Redcarpet)

chapter 9: Sinatra で遊んでみよう

$ gem install sinatra
$ ruby -rsinatra -e "get('/') { 'Fastest web development' }"
  • 少しアプリらしくする
Gemfile
app.rb
source "https://rubygems.org"
gem "sinatra"
require "sinatra"

get "/" do
  'Fastest web development'
end
$ bundle exec ruby app.rb

DSLと言う考え方

  • get ~ do でルーティングと処理を表現する
  • get はRubyのメソッドではなく、Sinatraがウェブのルーティングを表現するために追加した専用の言語
  • use, set なども追加される

問9-1

  • じゃんけんをするウェブアプリケーションを作ってみよう
require "sinatra"

get "/" do
  erb [(1)???]
end

[(2)???] "/result" do
  @choice = [(3)???]
  @op_choice = %w(goo choki paa).sample
  win_to_lose = {
    "goo" => "choki",
    "choki" => "paa",
    "paa" => "goo",
  }
  @result = if win_to_lose[@choice] == @op_choice
    "Won!"
  elsif @choice == @op_choice
    "Draw"
  else
    "Lost..."
  end
  erb :result
end

__END__
@ index
<html>
<h1>じゃんけん?</h1>
<form action='/result' method='post'>
  <select name='choice'>
    <option value='goo'>グー</option>
    <option value='choki'>チョキ</option>
    <option value='paa'>パー</option>
  </select>
<input type='submit' />
</form>
</html>

@ result
<html>
<h1>結果:</h1>
<p><%= [(4)???] %></p>
<p>自分:<%= [(5)???] %> 相手:<%= [(6)???] %></p>
</html>

問9-2

  • さっきのアプリケーションに、RubyのみでBasic認証の機能を追加するにはどうする?
    • ヒント: Rack Middleware

最後に: Ruby情報(日本語)

るりま

るびま

ドットインストール

Ruby Toolbox