最近、初めて Ruby でコードを書く機会があったので、Ruby の基本的なコマンドや、周辺技術についてまとめてみました。Ruby の文法についてはここでは触れません。
Ruby とは1995年に日本で開発されたオブジェクト志向スクリプト言語です。国内のスタートアップの企業の約1/4が自社サービスの開発に Ruby を採用していると言われており、PHPと並んで人気の言語となっています。また Ruby には高度なエコシステムが形成されており、フレームワークの開発やチームによる開発にも向いている言語と言われています。
Ruby には標準で以下のようなコマンドが用意されています。
rbenv
Ruby の環境設定を行うコマンドです。
Ruby のバージョン表示します。
rbenv --version
インストールされているRuby のバージョン一覧を表示します。
rbenv versions
Ruby のバージョンの選択します。
rbenv global 2.2.2
irb
Ruby のコードをインタプリタで実行するツールです。irb という名前は Interactive Ruby に由来しています。
irb を起動します。
irb
Ruby のコードを1行、1行実行できます。
ruby
ruby とは Ruby で書かれたコードを実行するコマンドです。
以下のようにソースファイルを指定して実行します。
ruby helloworld.rb
helloworld.rb
print("Hello World")
gem
gem とは Ruby で書かれたライブラリのことを指しており、gem を管理するコマンドも gem となっています。英語で宝石を意味する gem に由来しています。gemname.gemspec (gemname の部分は実際には gem の名前に置き換わります。)に gem に関する説明や、gem の依存関係を記述します。
gem のインストール
gem install gemname
gem のアンインストール
gem uninstall gemname
ローカルの gem をビルドします
gem build gemname.gemspec
ビルドした gem をインストールします
gem install ./gemname-0.1.0.gem
インストール済みの gem リスト表示
gem list --local
gemname.gemspec の内容
# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'my_gem_miura/version' Gem::Specification.new do |spec| spec.name = "my_gem_miura" spec.version = MyGemMiura::VERSION spec.authors = ["Kotaro Miura"] spec.email = ["miura@at-iroha.jp"] spec.summary = %q{Clac your age} spec.description = %q{This is an AIIT student's test program in Japan.} spec.homepage = "http://aiit.ac.jp" spec.license = "MIT" # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or # delete this section to allow pushing this gem to any host. if spec.respond_to?(:metadata) spec.metadata['allowed_push_host'] = "http://mygemserver.com" else raise "RubyGems 2.0 or newer is required to protect against public gem pushes." end spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.10" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "rspec" end
RubyGems
RubyGems とは Ruby のパッケージ管理システムです。RubyGems には誰もがライブラリを登録することができ、登録されたライブラリは gem コマンドにて簡単にインストールすることができます。
Rake
Rake とは Make によく似た機能を持つ Ruby で書かれたシンプルなビルドツールです。Rakefile を元にビルドを行います。
rake のインストール
gem install rake
Rakefile の記述例
require "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" t.libs << "lib" t.test_files = FileList['test/**/*_test.rb'] end task :default => :test
パターンにマッチしたタスクの短い説明を表示します
rake -T
テストを実行します
rake test
ビルドを実行します
rake build
Bundler
Bundler とはライブラリの依存関係の管理する技術です。gem は更新頻度が高く、バージョンによってプログラムが正常に動作しなくなる場合があります。その問題を解決するのが Bundler となります。Bundler は GemFile の記述を元に各種ライブラリを自動的にダウンロードします。bundle コマンドにて各種操作を行います。
Bundler の使い方
Gemfile のひな形を作成します。
bundle init
Gemfile に以下のように記述します。
source 'https://rubygems.org' gem 'nokogiri' gem 'rspec'
Gemfile の記述を元にインストールします。
bundle install
#bundle コマンドで gem を作成します。
bundle gem gemname
Minitest
Minittest とは Ruby に標準で搭載されている単体テストライブラリです。最近では Minitest よりもさらに高機能な RSpec も広く使われています。
テストコードの作成例
require 'test_helper' require 'gem_minitest' class GemMinitestTest < Minitest::Test def setup @my = GemMiniTest.new end #oddメソッドテスト #整数を入力として受け取り,値が奇数ならば真を返す def test_odd assert_equal(false, @my.odd(0)) assert_equal(true, @my.odd(1)) assert_equal(false, @my.odd(2)) end #check_numberメソッドテスト def test_check_number assert_equal(false, @my.check_number(0)) assert_equal(false, @my.check_number(123)) assert_equal(false, @my.check_number(1001)) assert_equal(true, @my.check_number(1000)) end #enough_lengthメソッドテスト def test_enough_length #境界値チェック2,3,8,9桁 assert_equal(false, @my.enough_length("12")) assert_equal(true, @my.enough_length("123")) assert_equal(true, @my.enough_length("12345678")) assert_equal(false, @my.enough_length("123456789")) end #divideメソッドテスト def test_divide assert_equal(2, @my.divide(50, 25)) assert_equal(20, @my.divide(200, 10)) end #fizz_buzzメソッドテスト def test_fizz_buzz assert_equal("", @my.fizz_buzz(0)) assert_equal("", @my.fizz_buzz(1)) assert_equal("Fizz", @my.fizz_buzz(3)) assert_equal("", @my.fizz_buzz(4)) assert_equal("Buzz", @my.fizz_buzz(5)) assert_equal("", @my.fizz_buzz(14)) assert_equal("FizzBuzz", @my.fizz_buzz(15)) assert_equal("", @my.fizz_buzz(16)) assert_equal("", @my.fizz_buzz(101)) end #引数に数値を1 つとる.3 の倍数の時は”Fizz”を返す.5 の倍数の時は”Buzz”を返す.3 と5 の公倍数のときは”FizzBuzz”を返す. def test_hello assert_output(/Hello/) { @my.hello} end end
テストするコード
require "gem_minitest/version" class GemMiniTest require 'time' require 'prime' #整数を入力として受け取り,値が奇数ならば真を返す def odd(num) if (num % 2)==1 then return true else return false end end #引数が0 以外ではじまる4 桁の数字であり,なおかつ,値が偶数ならば真を返す def check_number(num) #0チェック if num==0 then return false end #桁チェック if num.to_s.length != 4 then return false end #偶数チェック if odd(num) then return false else return true end end #文字列を受け取り,その長さが3 文字以上,8 文字以下であれば真を返す def enough_length(str) #最小値チェック if str.length < 3 then return false end #最大値チェック if str.length > 8 then return false end return true end #引数として割る数と割られる数を取り,割り算をした結果を返す.ただし,0 で割り算をしたら例外を発生する def divide(num_n, num_d) return (num_n / num_d).to_f end #引数に数値を1 つとる.3 の倍数の時は”Fizz”を返す.5 の倍数の時は”Buzz”を返す.3 と5 の公倍数のときは”FizzBuzz”を返す. def fizz_buzz(num) if num==0 then return "" end if (((num % 3)==0) && ((num % 5)==0)) then return "FizzBuzz" end if (num % 3)==0 then return "Fizz" end if (num % 5)==0 then return "Buzz" end return "" end #引数に数値を1 つとる.3 の倍数の時は”Fizz”を返す.5 の倍数の時は”Buzz”を返す.3 と5 の公倍数のときは”FizzBuzz”を返す. def hello() puts "Hello" end end
テストの実行
rake test
Guard
Guard とはファイルの変更などを監視し、タスクを自動的に実行するツールです。例えばエディタでソースコードを変更した際に、自動的にテストを実行させたい場合などに利用します。
Gemfile に guard を追加します
#開発環境でのみ guard を追加 group :develeoment do gem 'guard' end
Guardfile のひな形を作成します
bundle exec guard init
以下の様なファイルが自動生成されます。watch の部分などを環境に応じて変更します。
guard :minitest do # with Minitest::Unit watch(%r{^test/(.*)\/?test_(.*)\.rb$}) watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" } watch(%r{^test/test_helper\.rb$}) { 'test' } # with Minitest::Spec # watch(%r{^spec/(.*)_spec\.rb$}) # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } # watch(%r{^spec/spec_helper\.rb$}) { 'spec' } # Rails 4 # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" } # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' } # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" } # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" } # watch(%r{^test/.+_test\.rb$}) # watch(%r{^test/test_helper\.rb$}) { 'test' } # Rails < 4 # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" } # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" } # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" } end guard :bundler do require 'guard/bundler' require 'guard/bundler/verify' helper = Guard::Bundler::Verify.new files = ['Gemfile'] files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) } # Assume files are symlinked from somewhere files.each { |file| watch(helper.real_path(file)) } end guard :minitest do # with Minitest::Unit watch(%r{^test/(.*)\/?test_(.*)\.rb$}) watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" } watch(%r{^test/test_helper\.rb$}) { 'test' } # with Minitest::Spec # watch(%r{^spec/(.*)_spec\.rb$}) # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } # watch(%r{^spec/spec_helper\.rb$}) { 'spec' } # Rails 4 # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" } # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' } # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" } # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" } # watch(%r{^test/.+_test\.rb$}) # watch(%r{^test/test_helper\.rb$}) { 'test' } # Rails < 4 # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" } # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" } # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" } end
Guard を実行します
bundle exec guard
仮想環境を使用していて、ホストのテキストエディタによる変更にも反応させたい場合は、オプション -p を追加します
bundle exec guard -p
GitHub へのプッシュ方法
Ruby で開発したソースは git コマンドで直接、GitHub へプッシュすることが可能です。
Gitのリポジトリ作成を作成します。
git init
github上にリポジトリを作成
hub create
Git で管理する対象ファイルを指定します。「.」の場合、全てのファイルが対象となります。
git add .
ローカルリポジトリにコミットします。
git commit -m "first commit"
コミットした内容を GitHub 上にプッシュします。
git push -u origin master
Travis CI
Travis CI とは GitHub と連携し、GitHub 上のソースに変更が発生した場合、Travis CI に通知され、変更されたソースを自動でテストなどを行うWebサービスです。Ruby 以外にも様々な言語をサポートしています。CI は Continuous Integration (継続的統合) の略となっています。
.travis.yml ファイルに各種設定を記述します。
公式サイト
https://travis-ci.org/
GitHub 側の設定
1. プロジェクトのレポジトリを開きます。
2. [Setting] の [Werbhooks & Services] を選択します。
3. [Add Services] ボタンにて [Travis CI] を選択します。
設定後、GitHub のソースファイルに変更が発生すると、Travis CI 上で自動的にテストが実行されます。