Webエンジニアへの転職を目指して、現在Ruby、Railsを学習中。

【Ruby】%(パーセント)記法を覚える

はじめに

Rubyのコードを読んでいてたまに出てくる「%記法」(パーセント記法)について、毎回調べなくて良いように、簡単にまとめたいと思います。

記法 意味 式展開
%q シングルクウォート文字列 ×
%、%Q ダブルクォート文字列
%w 文字列の配列 ×
%W 文字列の配列
%i シンボルの配列 ×
%I シンボルの配列
%s シンボル ×
%x コマンド出力 -


%q

シングルクウォート文字列
式展開されない。

language = 'Ruby'

puts %q(#{language} is fun)    # => #{language} is fun


%、%Q

ダブルクォート文字列
式展開される。

language = 'Ruby'

puts %(#{language} is fun)    # => Ruby is fun

puts %Q(#{language} is fun)  # => Ruby is fun


%w

配列
要素が文字列で、要素間は空白区切り。式展開されない

language = 'Ruby'

%w(#{language} Java Python)    # => ["\#{language}", "Java", "Python"]


%W

配列
要素が文字列で、要素間は空白区切り。式展開される

language = 'Ruby'

%W(#{language} Java Python)    # => ["Ruby", "Java", "Python"]


%i

配列
要素がシンボルで、要素間は空白区切り。式展開されない

language = 'Ruby'

%i(#{language} Java Python)    # => [:"\#{language}", :Java, :Python]


%I

配列
要素がシンボルで、要素間は空白区切り。式展開される

language = 'Ruby'

%I(#{language} Java Python)    # => [:Ruby, :Java, :Python]


%s

シンボル。 式展開されない。

%s(Ruby)    # => :Ruby


%x

コマンド出力。 バッククウォート(`)で囲む場合と同じ。

puts %x(date)  # => 2019年 1月16日 水曜日 12時20分10秒 JST

【Rails】database.ymlの内容を理解する

はじめに

Active Record経由でデータベースに接続するには、config/database.ymlで接続設定を定義する必要があります。今回はデフォルトで記述されているdatabase.ymlの内容を解説したいと思います。

YAML形式で記述する

database.ymlはYAML形式で記述します。 YAML(YAML Ain’t Markup Language) は、名前にもあるように、マークアップ言語とは異なるため、構造をインデントや記号を使って書くことができます。そのため、マークアップ言語に比べて書きやすく、読みやすいという特徴があります。

デフォルトのdatabase.yml

以下は、railsアプリ作成時のデフォルトのdatabase.ymlです。

default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

test:
  <<: *default
  database: db/test.sqlite3

production:
  <<: *default
  database: db/production.sqlite3

基本的には、ハッシュのように、「パラメーター名:値」の形式で書きます。
また、半角スペースによるインデントを用いてハッシュをネストさせることで、階層をつけることができます。


パラメーターの概要

以下は、パラメーター名と概要です。

パラメーター名 概要
adapter 接続するDBの種類
pool 確保する接続プール
timeout 接続のタイムアウト時間(ミリ秒)
database DBの名前

ちなみにpoolの<%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>は、環境変数もしくは固定値の5を指定しています。


エイリアス設定とブロックの挿入でコードの重複を防ぐ

&エイリアスを意味します。エイリアスを付けておくことで、別の場所からそのブロックを引用することができます

default: &default   #エイリアスを設定している
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000


*は参照を意味し、<<: *別名で別名のブロックを挿入します。

development:
  <<: *default #defaultブロックを挿入している
  database: db/development.sqlite3


別名ブロックを挿入した結果、上記は以下と同じ意味になります。

development:
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  database: db/development.sqlite3

こうすることで、コードの重複を防ぐことができます。


参考文献

【Ruby】メソッドの引数の種類について

はじめに

Rubyのメソッドの引数の種類について、学んだことをまとめたいと思います。ruby2.5

今回取り上げる引数


デフォルト引数

を使って、引数にデフォルト値を設定できます。
引数なしでメソッドが呼び出された場合、デフォルト引数が渡されます。

def hoge(arg='hoge')
  p arg
end
hoge         #=> "hoge"
hoge("bar")  #=> "bar"


キーワード引数

ハッシュ形式で引数を設定できます。 メソッド呼び出し時はシンボル: 値の形式で引数を指定します。 引数の役割が明確になり、複数の引数を使うときに便利です。

def hoge(msg: 'hello', name: 'Sato')
  p "#{ msg }, #{ name }"
end
hoge(msg: 'hi', name: 'Yamada') #=> "hi, Yamada"

ハッシュなので順番は気にしなくて良い。

hoge(name: 'Yamada', msg: 'hi') #=> "hi, Yamada"

定義されていないキーは使えません。

hoge(age: 28) #=> ArgumentError (unknown keyword: age)

引数を省略するとデフォルトの値が返ります。

hoge                 #=> "hello, Sato"
hoge(name: 'Tanaka') #=> "hello, Tanaka"

定義時にデフォルト値を指定していなければ、引数を省略するとエラーになります。

def hoge(msg: 'hello', name: )
  p "#{ msg }, #{ name }"
end
hoge                 #=> ArgumentError (missing keyword: name)
hoge(name: 'Tanaka') #=> "hello, Tanaka"


可変長引数

*をつけて、複数個の引数を設定できます。引数は配列で受け取られます

def hoge(*arg)
  p arg
end
hoge                #=> []
hoge('a')           #=> ["a"]
hoge('a', 'b', 'c') #=> ["a", "b", "c"]


オプション引数

**をつけて、複数個の引数を設定できます。引数はハッシュで受け取られます。

def hoge(**arg)
  p arg
end
hoge                               #=> {}
hoge(a: 'foo')                 #=> {:a=>"foo"}
hoge(a: 'foo', b: 'bar', c: 'baz') #=> {:a=>"foo", :b=>"bar", :c=>"baz"}


ブロック引数

&をつけることで、ブロックを引数として受け取ることができます。 メソッド内でcallで処理を呼び出します。

def hoge(&arg)
  arg.call
end
hoge { 1 + 2 }  
#=> 3   

hoge do 
  ['foo', 'bar', 'baz'].join(',')
end
#=> "foo,bar,baz"


下記のようにyieldで書くこともできます。こちらのほうがよく使われるようです。

def hoge
  yield
end
hoge { 1 + 2 }  
#=> 3   

hoge do 
  ['foo', 'bar', 'baz'].join(',')
end
#=> "foo,bar,baz"

使い方、結果は&と同じです。

参考ページ

https://qiita.com/rtoya/items/33617078501776fdcad7

参考文献

【Ruby】トップレベルとは

はじめに

Rubyのトップレベルについて、私自身あまり理解できていなかったので、学んだことをまとめたいと思います。

トップレベルとは

トップレベルとは、クラス構文やモジュール構文に囲まれていない一番外側の部分のことを言います。

また、トップレベルでselfを表すオブジェクトはmainです。mainは、トップレベルからselfで参照できます。 Ruby リファレンスマニュアル

irbで確認してみる

トップレベルはクラス構文やモジュール構文に囲まれていない一番外側と考えると、irbを起動した直後にいる場所もトップレベルにあたります。

#irb

self
#=> main

self.class
#=> Object

上記のように、 irb起動時にselfで参照すると、mainが返ってきます。また、self.classでObjectが返ってくることから、mainはObjectクラスのインスタンスであることが分かります。

トップレベルでメソッドを定義する

トップレベルで定義したメソッドは、Objectクラスのインスタンスメソッドとして定義されます。

#irb

def top_method; "top_method"; end

Object.instance_methods.grep(/top_method/)
#=> [:top_method]

Rubyはすべてがオブジェクトであり、ClassクラスやModuleクラスも大半はObjectクラスを継承していることから、トップレベルで定義したメソッドは、どこからでも呼び出すことができるようになっています。

参考ページ

Ruby リファレンスマニュアル

参考文献

【Ruby】モジュールのincludeとextendの違い

はじめに

Rubyのモジュールをミックスインする方法として、includeextendがありますが、この2つの違いについて、学んだことをまとめたいと思います。

結論

ミックスインされるモジュールに定義されたメソッドをどう呼び出すか、という点で2つは異なります。 includeインスタンスメソッドとして、extendはクラスメソッドとして呼び出します。

実際のコード

  • include

module M
  def method_m; "method_m"; end
end

class A
  include M
end

a = A.new

a.method_m
#=> "method_m"

A.method_m
#=> NoMethodError: undefined method `method_m' for A:Class

MモジュールをincludeしたAクラスでは、Mで定義されたmethod_mインスタンスメソッドとして呼び出されています。

  • extend

module M
  def method_m; "method_m"; end
end

class B 
  extend M
end

b = B.new

b.method_m
#=> NoMethodError: undefined method `method_m'...

B.method_m
#=> "method_m"

MモジュールをextendしたBクラスでは、Mで定義されたmethod_mがクラスメソッドとして呼び出されています。

【Ruby】メソッドが定義されているクラスを調べる

はじめに

Rubyでは、メソッドはクラス(またはモジュール)内に定義されます。呼び出したメソッドがどのクラスで定義されているのか知りたい時、ownerメソッドが便利だなあと思ったので、その使い方をまとめたいと思います。

ownerメソッドとは

ownerメソッドは、RubyMethodクラスに定義されているインスタンスメソッドです。メソッドが定義されている class か module を返しますRuby 2.5.0 リファレンスマニュアル

実際に使ってみる

class A
  def method_a; end
end

a = A.new

a.method(:method_a).owner
#=> A          

method_aが定義されているAクラスを返しています。

上記では、以下のように、a.method(:method_a)で、Methodクラスのインスタンスを生成し、それに対してownerメソッドを呼び出しています。

a.method(:method_a).class

#=> Method          

このように、ownerメソッドが定義されているMethodクラスは、Object#method によりオブジェクト化されたメソッドオブジェクトのクラスです。Ruby 2.5.0 リファレンスマニュアル

継承されたメソッドも同様

継承されたメソッドも同様に調べることができます。

class A
  def method_a; end
end

class B < A; end

b = B.new

b.method(:method_a).owner
#=> A                   

上記は、Aクラスを返します。

module M
  def method_m; end
end

class A
  include M
end

class B < A; end

b = B.new

b.method(:method_m).owner
#=> M                   

上記は、Mモジュールを返します。

このように、ownerでメソッドが定義されたクラスもしくはモジュールを調べることができました。

まとめ

呼び出しているメソッドの定義場所を調べることで、そのオブジェクトが継承しているクラスやモジュールを認識できるのが個人的に便利だなあと思いました。

【Ruby】メソッド呼び出し時の「メソッド探索」を理解する

はじめに

これまでRubyのメソッド呼び出しについて深く考えたことがありませんでしたが、そのプロセスを理解することはオブジェクト指向設計を理解するために必要と感じたので、今回はRubyメソッド探索について学んだことをまとめたいと思います。

メソッド探索とは

Rubyに限らず、オブジェクト指向言語では、メソッドを呼び出す時に、メソッドを探す → メソッドを実行するというプロセスを経てメソッドを呼び出しています。このメソッドを探すという処理がメソッド探索にあたります。

メソッド探索のプロセス

メソッド探索では、レシーバのクラスを探索してメソッドを発見しています。具体的には、まずレシーバのクラスに入り、メソッドを探します。そこで見つからなければ継承しているスーパークラスを順に辿って行き、Rubyのクラス階層のルートにあたるBasicObjectクラスまでメソッドを探しに行きます。この過程を継承チェーンと呼び、継承チェーンの道筋には、モジュールも含まれます。

継承チェーンの確認方法

継承チェーンはancestorsメソッドで確認できます。

実際のコードで確認してみる。

module M
  def method_m
    "method_m"
  end
end


class A
  include M
end


class B < A; end


B.ancestors
# => [B, A, M, Object, Kernel, BasicObject]            

上記はBクラスの継承チェーンを表示しています。

従って、以下のように、BクラスのインスタンスはMモジュールのメソッドを呼び出すことができます。

b = B.new


b.method_m
# => "method_m" 
        

上記では、bに対して呼び出されたmethod_mは、B → A → Mと継承チェーンを辿ってメソッドを発見しています。

参考文献