【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】モジュールのincludeとextendの違い
はじめに
Rubyのモジュールをミックスインする方法として、include
とextend
がありますが、この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
メソッドは、RubyのMethodクラスに定義されているインスタンスメソッドです。メソッドが定義されている 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と継承チェーンを辿ってメソッドを発見しています。