【Week 7】gem, ruby_third



# はじめに

マルチスケールシミュレーション特論の講義メモです．講義メモのインデックスは[コチラ](<https://qiita.com/e79a93e5b7b1/items/d48ad7b8df544d737a78>)．

今回の参考資料は[チャート式ruby-appendix-III(bundler)](<https://qiita.com/daddygongon/items/14218c96df5cbcf35c62>)と[チャート式ruby-III(if, case, Array.each by leap year)](<https://qiita.com/daddygongon/items/a550bde1ed6bff5217d8>)です．


# チャート式 Ruby

参照記事は[コチラ](<https://qiita.com/daddygongon/items/a550bde1ed6bff5217d8>)


## if-else, case, array and each


### 閏年判定プログラム

プログラミング初心者に条件分岐を教えるとき，題材としてよく挙げられるのが閏年．今年２０２０年は閏年だったが，一体どれくらいの人が気にしていたのだろうか．恐らく大半はプログラミング初学者で条件分岐習った人（偏見）．

それはともかく，閏年の判定プログラムを作成したい．閏年は

1.  4で割り切れる年．
2.  ただし，100 で割り切れる年は閏年でない．
3.  しかし，400 で割り切れる年は閏年．

の条件によって判定される．なぜこのような条件なのかは，気持ちに余裕があれば追記する．

参照記事にあるとおり閏年の判定は ~~ひねくれた~~ 複雑な条件分岐であるため，あらかじめ考えて実装するのは面倒．そこで今回は順を追って TDD （テスト駆動開発）で実装していく．


### if-elsif-else-end

まず Ruby における if 文の文法をおさえておく．条件分岐といえば if 文というくらい重要な項目ではあるが，言語によって若干仕様が異なってくるので，多少プログラミングに慣れていても注意が必要である．

```ruby
if 式 then
  式 ...
elsif 式 then
  式 ... 
...
else
  式 ... 
end
```

それでは閏年判定プログラム check\_leap\_year.rb を作成していく．はじめに `1. 4で割り切れる年` であれば true を返すようなプログラムを実装する．

```ruby
p year = ARGV[0].to_i
if year%4==0 then
  p true
end
```

試しに 2004 を引数として実行すると，

    > ruby check_leap_year.rb 2004
    2004
    true

期待通り true を返した． 4で割り切れない 1999 を引数として実行すると，

    > ruby check_leap_year.rb 1999
    1999

このとき，true は出力されない．このように4で割り切れない年であれば false を返すようにしたい．else 文を用いて以下のように編集する．

```ruby
p year = ARGV[0].to_i                                                                          
if year%4==0 then                                                                              
  p true                                                                                       
else                                                                                           
  p false                                                                                      
end       
```

実行すると，

    > ruby check_leap_year_0.rb 1999
    1999
    false

期待通り false を返した．


### array, each

ここで`2. 100 で割り切れる年は閏年でない`

```ruby
[1900,2004,1999].each do |year|
  p year
  if year % 100 ==0
    p false
  elsif year % 4 == 0
    p true
  else
    p false
  end
end
```

    > ruby check_leap_1900_2004_1999.rb 
    1900
    false
    2004
    true
    1999
    false

`3. 400 で割り切れる年は閏年`

```ruby
def leap?(year)
  if year % 400 ==0
    p true
  elsif year % 100 ==0
    p false
  elsif year % 4 == 0
    p true
  else
    p false
  end 
end

[2000, 1900, 2004, 1999].each do |year|
  p year
  leap?(year)
end
```

    > ruby check_leap_year.rb
    2000
    true
    1900
    false
    2004
    true
    1999
    false


### case

```ruby
case 式
when 式 ..., then
  式..
when '*' 式 then
  式..
else
  式..
end
```

```ruby
def leap?(year)
  case 
  when year == 2000 ; p true
  when year == 1900 ; p false
  when year == 2004 ; p true
  else              ; p false
  end
end
[2000, 1900, 2004, 1999].each do |year|
  p year
  leap?(year)
end
```


### 三項演算子 (ternary operator)

```ruby
def leap?(year)
  return  (year%400 == 0) ? true :
    (year%100 == 0) ? false :
    (year%4 == 0) ? true : false
end

[2004, 1999, 1900, 2000].each do |year|
  p year
  p leap?(year)
end
```


# Ruby 開発周辺情報

参照記事は[コチラ](<https://qiita.com/daddygongon/items/14218c96df5cbcf35c62>)


## shebang

前回の講義で作成し，UI-like にリファクタリングしたプログラム hello.rb を実行ファイルにしたい．これはシバン (shebang) を設定し，ファイルの権限を変更することで実現できる．

    > cp hello.rb hello
    # hello.rb を hello にコピー
    
    > emacs hello
    # hello を編集

プログラムのはじめにシバンを設定する．

```ruby
#! /usr/bin/env ruby
def puts_hello name...end
def gets_name ...end

name = gets_name
puts_hello name
```

hello\_rudy.rb に実行権限を付与する．

    > chmod a+x hello
    または
    > chmod 755 hello
    
    > ./hello Rudy
    Hello Rudy.

期待どおり実行ファイル hello を作成することができた．


## gem


### bundler

shebang だと PATH を通したり実行環境を整えるのに手間がかかる．そこで実行ファイルを gem にすることで容易に呼び出せるようにしたい．

gem を作成するには bundler を使って環境を構築する必要がある．まずは参照記事どおり bundler をインストールし，gem 作成用のファイル環境を構築する．

    > sudo gem install bundler
    Password:
    Successfully installed bundler-2.1.4
    Parsing documentation for bundler-2.1.4
    Done installing documentation for bundler after 2 seconds
    1 gem installed
    
    > bundle gem hello_rudy -b
    Creating gem 'hello_rudy'...
    MIT License enabled in config
    Code of conduct enabled in config
          create  hello_rudy/Gemfile
          create  hello_rudy/lib/hello_rudy.rb
          create  hello_rudy/lib/hello_rudy/version.rb
          create  hello_rudy/hello_rudy.gemspec
          create  hello_rudy/Rakefile
          create  hello_rudy/README.md
          create  hello_rudy/bin/console
          create  hello_rudy/bin/setup
          create  hello_rudy/.gitignore
          create  hello_rudy/.travis.yml
          create  hello_rudy/test/test_helper.rb
          create  hello_rudy/test/hello_rudy_test.rb
          create  hello_rudy/LICENSE.txt
          create  hello_rudy/CODE_OF_CONDUCT.md
          create  hello_rudy/exe/hello_rudy
    Initializing git repo in ~/grad_members_20f/members/e79a93e5b7b1/codes/hello_rudy
    Gem 'hello_rudy' was successfully created. For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html

hello\_rudy というディレクトリが作成され，そこに gem の作成に必要なファイルが生成される．その中のひとつに .git という隠しディレクトリが存在するが，今回は必要ないので削除しておく．

これで gem を作成するファイル環境は構築できた．続いて，実行ファイル hello\_rudy が実行できるように編集していく．

    > rm -rf hello_rudy/.git
    
    > cd hello_rudy
    > bundle exec exe/hello_rudy 
    bundler: not executable: exe/hello_rudy
    
    > chmod a+x exe/hogehoge
    > bundle exec exe/hello_rudy
    bundler: failed to load command: exe/hello_rudy (exe/hello_rudy)
    Gem::InvalidSpecificationException: The gemspec at ~/grad_members_20f/members/e79a93e5b7b1/codes/hello_rudy/hello_rudy.gemspec is not valid. Please fix this gemspec.
    The validation error was 'metadata['homepage_uri'] has invalid link: "TODO: Put your gem's website or public repo URL here."'
    
    > emacs hello_rudy.gemspec 

エラー内容の該当ファイル hello\_rudy.gemspec を編集する必要がある．

`spec.summary` `spec.description` `spec.homepage` の３つは "TODO:~" の部分を削除し，内容に沿って適宜編集する．また， `spec.metadata["homepage_uri"]` `spec.metadata["source_code_uri"]` `spec.metadata["changelog_uri"]` はコメントアウトしておく．

```el
require_relative 'lib/hello_rudy/version'

Gem::Specification.new do |spec|
  spec.name          = "hello_rudy"
  spec.version       = HelloRudy::VERSION
  spec.authors       = ["e79a93e5b7b1"]
  spec.email         = ["e79a93e5b7b1@xxx.com"]

  spec.summary       = %q{Hello Rudy.}
  spec.description   = %q{Hello Rudy.}
  spec.homepage      = "https://github.com/TeamNishitani/grad_members_20f/member/e79a93e5b7b1"
  spec.license       = "MIT"
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")

  spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"

  # spec.metadata["homepage_uri"] = spec.homepage
  # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
  # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
```

編集を保存した後，再度実行してみる．

    > bundle exec exe/hello_rudy
    > emacs lib/hello_rudy.rb

エラーもなくなり，問題なく hello\_rudy を実行できるようになった．本題の "Hello xxx." を出力するプログラムは /hello\_rudy/lib/hello\_rudy.rb に記述する．

```ruby
require "hello_rudy/version"

module HelloRudy
  class Error < StandardError; end
  # Your code goes here...
  puts "Hello #{ARGV[0]}."
end
```

プログラムを保存した後，引数を付け足して実行してみる．問題なく出力されれば gem をインストールする．

    > bundle exec exe/hello_rudy Rudy
    Hello Rudy.
    
    > sudo rake install:local
    Password:
    hello_rudy 0.1.0 built to pkg/hello_rudy-0.1.0.gem.
    hello_rudy (0.1.0) installed.
    
    > hello_rudy Rudy
    Hello Rudy.

問題なく実行ファイルを gem にすることができた．


## Directory\_tree

bundle を用いることで以下のようなファイル環境が自動で作成された．

    > tree
    .(hello_rudy)
    ├── CODE_OF_CONDUCT.md
    ├── Gemfile
    ├── Gemfile.lock
    ├── LICENSE.txt
    ├── README.md
    ├── Rakefile
    ├── bin
    │   ├── console
    │   └── setup
    ├── exe
    │   └── hello_rudy
    ├── hello_rudy.gemspec
    ├── hello_rudy.gemspec~
    ├── lib
    │   ├── hello_rudy
    │   │   └── version.rb
    │   ├── hello_rudy.rb
    │   └── hello_rudy.rb~
    ├── pkg
    │   └── hello_rudy-0.1.0.gem
    └── test
        ├── hello_rudy_test.rb
        └── test_helper.rb
    
    6 directories, 17 files


# 次回の講義内容 <span class="timestamp-wrapper"><span class="timestamp">&lt;2020-11-11 Wed&gt;</span></span>

次回の講義は

-   [rake](<https://qiita.com/daddygongon/items/1c2d6d2895333ccf5e62>)

だそうです．



------
 - **source** ~/grad_members_20f/members/e79a93e5b7b1/posts/class/c7_20201104.org