基本的なルール
四則演算
四則演算(加減乗除)はそれぞれ+, -, *, /, % これは一般的。
プログラミング独特なのは%。%は割った余りを出す。15%4だと3が返る。
累乗は**
Rubyの文字連結
“aaa” + “bbb”
&じゃない。
正誤判定
A == B 同じかどうか判定
バックスラッシュ記法
””で囲った文字列内でのみ有効。
’hoge\nhoge’では無効。
ちなみに”\”の入力はoption + ¥
\n 改行
\t タブ
\b バックスペース
\\ バックスラッシュ
#{} 式展開
””内に#{変数やメソッド}とすると展開される。
num = 5
puts "数字は#{num}です"
=> 数字は5です
ハッシュ(key, value)
キーと値をセットで格納している。
{キー1 => 値1,キー2 => 値2, … }
ハッシュは色々な書き方ができる。
コードが短いので一番下の書き方を通常使う。
hash1 = {"title" => "hogehoge"}
hash2 = {:title => "hogehoge"}
hash3 = {title: "hogehoge"}
上は文字列、下2つはシンボル指定
:hogehogeのように:が付いているのがシンボル。
シンボルと文字列は同様の動きをするが内部的に異なる。
シンボルは整数として内部的に扱っているので処理が早い。
データを取り出す際は、ハッシュ名[:キー]
ハッシュに値を追加
hash[:key] = 値
もしくは
ハッシュオブジェクト.store(key, value)
配列[]
ハッシュはハッシュ名.{key: value, }
配列は配列名[]
配列の場合は中に入れるのはなんでも良い。数字や文字列でもいいし、ハッシュやインスタンスを入れることもできる。なんでもOK.
配列内のデータを取り出す際は、配列名.[3]のようにすると取り出せる。
1つ目のデータは配列名.[0]から始まる。
Rangeクラス
配列同様にeachが使える。
範囲指定は文字でもOK。
1..5 1,2,3,4,5
1…5 1,2,3,4 (指定した終末を含まない)
Range.new(1,5)
Range.new(1, 5, true) 上と同義。
RubyにおけるTime
似たようなクラスにDateクラスやTimeWithZoneクラスがある。
DBに型をTIMEで作成し、例として15:00:00を格納した場合にputsすると
=> Sat, 01 Jan 2000 15:00:00 UTC +00:00
rubyではTIMEのみで扱えない。強制的に日付がつく。
引数
デフォルト引数
引数は左から順に読まれ、引数がなかった場合に=の右辺が代入される
hoge(fuga="fooo")
hoge => "fooo"
可変長引数
*をつけると可変長な引数となる。要は配列で指定し放題。
def hoge(*fuga)
put fuga
end
hoge("aaa","abb","abc")
=> ["aaa","abb","abc"]
キーワード引数
引数をハッシュで宣言できる。
宣言順を考慮しなくて良いので扱いやすい反面、キーを入力しないといけないので面倒。
def self.hoge(name: 'satou', text: 'hello' )
p "#{name}, #{text}"
end
hoge(name: "yamada", text: "fuga")
クラスとインスタンス
クラスという大きな括りがあって、その中の個別の事象をインスタンスという。
1つ1つの事象はオブジェクトと呼ばれる。
具体的には犬クラスがあって、柴犬というインスタンスがある。
クラス
クラスの定義は以下のように行う。
クラスは定数として書かなければならず、先頭の文字は大文字にする。
class Hogehoge
end
クラス同士で親子関係を持つことができ、その場合は以下のように記述する。
class 子クラス < 親クラス
クラスメソッド
クラスメソッドにはメソッド名の前にself.をつける。
classオブジェクト以外からこのメソッドを呼び出すことはできない。
def self.メソッド名
end
インスタンスメソッド
クラスメソッドと違い、selfはいらない。
同クラスのインスタンスからしかこのメソッドは呼べないので、インスタンスも生成してインスタンス.メソッド名としないと使えない。
def メソッド名
end
クラス変数とインスタンス変数
クラス変数は@@クラス変数と指定する。
インスタンス変数は@インスタンス変数と指定する。
単にクラスを定義しただけだと変数を取り出すのが面倒なので、後述するゲッターやセッターを用いて変数の中身を取り出す。
ゲッターとセッター
ゲッター
インスタンスから属性値を取り出す際に使うメソッドのこと。
属性名に対応するメソッドを作って属性値を返すように設定しておくことで、コードが書きやすくなる。
def instance.zokusei
return @zokusei
end
セッター
インスタンスの属性値を入力する際に使う。
def instance.zokusei=[a,b,c,d]
@zokusei = [a,b,c,d]
end
メソッド名はスペースがあっても読み飛ばされるので
instance.zokusei = [a,b,c,d]
と書けばまるで右辺の値が代入している式のようにみえる。
実際にはinstance.zokusei=[a,b,c,d]メソッドが実行されている。
attr_accessor
ゲッター・セッターともに非常に利用頻度が高いので、毎回2つずつ定義するのは面倒。
なので直訳すると属性アクセッサーなるメソッドを用いて簡略化できる。
class Dog
attr_accessor :name, :type. :sex
end
こうするとname,type,sexの属性について前述のゲッターとセッターが設定される。
attr_accessor, attr_reader, attr_writer
attr_accessor ゲッターとセッター
attr_reader ゲッターのみ
attr_writer セッターのみ
initializeメソッド
class = Class.new() などでインスタンスが生成された際に呼ばれるメソッド。
変数等の初期値を入力するために利用する。
自動的には作られないので.new()する可能性があれば自分で定義する。
以下のように定義しておくと、インスタンス変数に値を入れてくれる。
なおClass.new(A, B)としても結果は同じ。
initialize(A, B)
@zokusei1 = A
@zokusei2 = B
こんな風に書くこともできる。
class Customer
def initialize(name, money, ticket=nil)
@name, @money, @ticket = name, money, ticket
end
end
デフォルト引数
下のticket = nilのように書いてあるもの。引数がない場合にnilが代入される
class Customer
def initialize(name, money, ticket=nil)
@name, @money, @ticket = name, money, ticket
end
end
命名規則
変数名
小文字から始める。数字スタートはだめ。 予約語も当然ダメ。
定数
大文字から始める。慣例として全て大文字を使う。
rubyの定数は、再代入しようとすると警告がでるものの代入される(されてしまう)。実質的には変数名と差がないように思う。
メソッドの定義の仕方
defで宣言し、endで終わる。
def メソッド名
end
method名(引数)とすると外部の数字を引ける。
グローバル変数ならいつでも引ける。
変数には参照できる範囲が限られている。
複数ファイルにまたがるファイルの管理
カレントディレクトリの他のファイル(ライブラリ)を参照させたい場合にはrequireメソッドを用いて記述する。この際、読み込むファイルの拡張子は記載する必要がない。
require ‘./customer’
require ‘./movie
頻出メソッド
.print / .puts
- print 改行なし
- puts 改行あり
.length
“hogehoge”.length -> 8を返す。文字数を数える。
.to_s / to_i
StringとIntegerの略。
文字列に変換したり、数字に変換したりしてくれる。
文字列を数字に変換した場合は0となる。
input = getsした際には文字列で格納されるので.to_iや.chompをよく使う
.chomp
文字列の最後に付く改行を消してくれる。
特にgetsで文字列を取得した場合には文末に改行が付与されるため、それを削るためにgets.chompとして使う。
getsメソッド
処理を止めてターミナルに入力させる。
データは文字列で取得する。
文末に改行を仕込むので.chompで取り除くのが吉。
配列名.each do |適当な名前|
.eachとすることで、配列内の全ての要素に対して処理をループできる。
hogehoge.each do |hoge|
puts hoge
end
このようにするとhogehogeという配列内の全ての要素を出力できる。
each.with_index
eachメソッドと with_indexメソッドを併用すると、要素の数だけブロックを繰り返し実行し、繰り返しごとに | で囲われている部分の i に番号が入る。デフォルトでは、iには0から入ります。
<% @ranking.each.with_index(1) do |product, i| %>
<% end %>
.each_with_index と .each.with_index()
.each_with_index do |hogehoge, index|
indexの番号は0から始まる。
.each.with_index(数字) do|hogehoge, index|
indexの番号は指定した数字から始まる。
keysメソッド
ハッシュはkeysというメソッドを持つ。
ハッシュのキーだけを取り出して配列として返す。
valuesメソッド
ハッシュはvaluesというメソッドを持つ。
ハッシュのバリューだけを取り出して配列として返す。
.sum
配列の中身を合計してくれる。
array.sum
mapメソッド
配列オブジェクトのインスタンスメソッド。
配列の中身を1つずつ取り出してブロックという構文を繰り返し実行し、ブロックの返り値を集めた新しい配列を作成する。
配列オブジェクト.map {|ele| ブロックの処理}
# eleには配列の要素が1つずつ代入される
# ブロックの処理は配列の要素の数だけ繰り返し実行される
ランキング機能の実例
def ranking
product_ids = Review.group(:product_id).order('count_product_id DESC').limit(5).count(:product_id).keys
@ranking = product_ids.map{|id| Product.find(id) }
end
実はハッシュに対しても使える。
その場合も返り値はハッシュではなく配列になる。
hogehoge = {id: 5, price: 10}
hogehoge.map { |key, value| [key, value * 2] }
=> [[:id, 10], [:price, 20]]
hogehoge.map { |key, value| [key, value * 2] }.to_h
=> {:id=>10, :price=>20}
map { |key, value| value}
valueだけ取り出した配列が返る。
to_h
ハッシュに変換してくれる
.inject
隣り合う要素に対して処理をする。reduceと同じ。
array.inject(:+)
.pop
array.pop
配列の最後の要素を削除。
slice, delete_at, shift等
文字列の大文字・小文字を変換
- downcase ・・・ 大文字を小文字に変換
- upcase ・・・ 小文字を大文字に変換
- swapcase ・・・ 小文字⇔大文字の変換
- capitalize ・・・ 先頭の小文字を大文字に変換
split()
文字列を分割
引数を文字で指定すればその文字で分割。無指定なら半角スペースで分割。
空白を削除
.stripメソッドを持ちる。文字間の空白は消さず、両サイドの空白を消す。
.lstrip 左側だけを消す。
.rstrip 右側だけを消す。
.strftime
string format timeだと思う。
日付や時間形式のデータを扱う際に任意のフォーマットへ変換する。
例
time.strftime("%Y/%m/%d/ %H:%M:%S")
基本は%+大文字のアルファベットにしておけば、常時2桁(年は4桁)となる。
Yearを除き、可変表記にするには%-mや%-dのようにマイナスで繋ぐ。
mはMonthとMinutesでダブるため、month・dayはセットで小文字表記になる。
Array.index(object)
オブジェクトに一致した配列要素の位置を数字で返す。
1番目が0。
array = [1,2,3]
array.index(3)
=> 2
.first / .last
array.firstという風に使う。
文字通り配列の1番目の値を返す。lastなら最後の値。
引数にnumを指定でき、その場合は先頭からnum個の配列を返す。
要素数を超える数字を指定しても元の配列を返すだけ。
arr = [1,2,3,4,5,6,7,8,9]
arr.first => 1
arr.first(3) => [1,2,3]
便利なメソッド(確認用)
is_a?(), kind_of?()
is_a?(Hash)
is_a?(Array)
kind_of?(Hash)
kind_of?(Array)
kind_of?(Object)
kind_of?(Enumerable)
is_a?(Hash)が機能していない場合、respond_to?(:key)でtrueならハッシュのはず。
.even? と .odd?
変数.even? とすると true/falseが返る。
3.even? => false
.nil?
nilかどうかを判定してくれる。
nil なら true
nil でなければ false
データベース上がNULLでもRubyでは.nil? => Trueとなる。
to_sql
sql文を返す。
使ったことがないのでなんとも。
order.countやorder.limitなどで謎な挙動をした際に調べるのに使えるかも。
今の私にはSQL文を読むのは荷が重い。
.any? {|item| block }
配列に対して処理する。block内での処理でtrueが返ればtrueを。
配列が空であったり、処理結果が全てfalseだった場合にfalseを返す。
sort
配列に対して使う。並び替えをする関数。
比較には<=>が使われる。
昇順で並び替え
array.sort
降順で並び替え
array.sort {|a, b| b<=>a }
compact, compact!(nilの要素を削除)
配列に対して使う。nilの要素を削除してくれる。
select
条件に会う要素を取得する。
array.select { |a| 条件 }
delete_if
array = (1..5).to_a.delete_if { |el| el.even? }
array = (1..5).to_a.delete_if(&:even?)
条件式
if文
if ** then
elsif then
else
end
elseとelsifでEの有無が違う。(初見で間違えた)
if文中の複合条件は以下のように指定する。
A&&B AかつB
A||B AまたはB
後置することも可能で、その場合は条件がtrueの時のみ実行される。
可読性は上がるが、条件式がfalseだった場合に返り値はnilがくるので注意。
puts "hogehoge" if 条件式
unless文
if文の逆で上限がflaseの時に実行。
if文もunless文も1行で条件が表記できる場合は1行で表記できる。
puts 'ログインをしてください' unless user_signed_in?
# 以下と同義
unless user_signed_in?
puts 'ログインをしてください'
end
三項演算式
条件式 ? 真の時の値 : 偽の時の値
a==b ? true : false
if文と変わらないが、内容が簡潔であれば短くかける。
while文
条件がtrueの場合に繰り返す。
なおdoは省略可能。処理を抜ける際にはbreakを使う。
while 条件式 do
end
until文
whileとほぼ同じ。if/unlessと似たような関係。
条件がtrueになるまで処理を繰り返す。
処理を抜ける際にはbreakを使う。
exitメソッド
プログラムの処理を強制的に終了させるメソッド。
プログラム自体を強制終了させるのでexitメソッド以降の処理は行われない。
while true do
exit # ここでプログラムが終わる
puts "Hello World" # これは呼ばれない
end
case〜when
case 評価対象1
when 評価対象2
when
else
end
評価対象1==評価対象2の時、when以下が実行される。
その下の条件に関しては読まれない。1つ目のwhenを実行した時点で処理を抜ける。
宇宙船演算子 <=>
条件式ではないが、条件として使うのでここに。
A < Bなら-1を、A == Bなら0を、A > Bなら1を返す。
演算子の左を起点に左の方が小さければマイナス、大きければプラスと覚える。
.sortと組み合わせて並び替えに使ったりもする。
=~演算子(メソッド)
正規表現とのパターンマッチを行う。
マッチした場合、マッチした位置を整数で返す。
マッチしなかった場合、nilを返す。
/ETF|JDR/ =~ com_name
Regexpクラスのメソッド 正規表現 =~ string
stringクラスのメソッド string =~ 正規表現
の2つがあるが、実質的に挙動が同じ。
string.include?(“hogehoge”)などで複数条件で指定したい場合には、include?の表現に限界があるので=~を使う。
キーワード:複数文字列 検索 マッチ
繰り返し処理
for文
doは省略可能。
実行される内容にeachが走るので、指定するオブジェクトはeachを使えるオブジェクトのみ。
eachがあるのでrubyではあまり出番がない。
for 変数 in オブジェクト do
実行する処理
end
for num in 0..99 do
puts num
end
.times
object.times {処理}
例
10.times {puts "aaa"}
0 〜(オブジェクト内の数値-1)まで繰り返す。
.upto / .downto
object.upto(max) {処理}
object.downto(max) {処理}
例
5.upto(10) {puts "aaa"}
(オブジェクト内の数値)〜maxまでの値まで繰り返す。
上の例の場合、5,6,7,8,9,10と6回繰り返す。
再起関数・多重ループ
再帰関数
関数内に自分を呼び出す関数。内部ループしているが、最終的に値が収束するように設計する。
def sum(num)
if num==0
return 0
else
return num+sum(num-1)
end
end
sai(3)
多重ループ
whileやif文などの条件式をネストさせたもの。
深いメソッドのネストを抜ける方法
多言語ではgotoなどを使う。(好まれないが)
rubyでは catch ~ throw がgotoに類似した機能。(あまり使われない)
begin ~ rescueとraiseを組み合わせるパターンがよく使われる。
begin ~ rescue
処理内で例外が発生した場合、rescueが実行される。
またensureを用いると、例外発生の有無にかかわらずensure句は実行される。
raise/fail 強制的にエラーを起こす。
どちらも同じだが、raiseは意図的にエラーを起こしてrescueで再キャッチする際に用いる。
catch ~ throw
リファレンスマニュアルから抜粋
result = catch do |tag|
for i in 1..2
for j in 1..2
for k in 1..2
throw tag, k
end
end
end
end
p result #=> 1
catchで指定したタグ をthrowで受けた時に処理を一気に抜ける。
%記法
”や’、\(エスケープ)の記述を省略し、可読性をあげる記法
%Q %q
文字列用の記法
%Q(“aaa”)
\”aaa\”
%W %w
配列を作成する記法。
%Wは式展開あり。%wは式展開なし。
%w(日 月 火 水 木 金 土)
["日", "火", "水", "木", "金", "土"]
require 'date'
a = Date.today.wday
arr = %w(日 月 火 水 木 金 土)
print "今日は#{arr[a]}曜日"
puts "da!!" if a==6
Rubyのバージョン管理とGemのバージョン管理
rubyはrubyで、gemはgemで独立して管理されている。
間違い -ruby 1 - gem1,gem2,gem3 -ruby 2 - gem1,gem2,gem3 正解 -Ruby- ruby1, ruby2 -gem - gem1, gem2, gem3
同一gemの別バージョンも同じように管理されているため、porjectが増えるとバージョンが混在して依存関係で問題がでる。このような場合にはbundle execをつけて実行することでgemfile内の情報を辿って指定のバージョンのgemを利用できる。
ざっくり言えばエラーが出ない限りはbundle execを付ける意味はない。エラーが出たらbundle execをつけましょう。
irbコマンド
ターミナル上からrubyを試せる。
railsの場合はrails c。
.methods と .methods(:メソッド名).owner
使えるメソッドの一覧を取得。
.ownerでそのメソッドの定義元を確認できる。
a = 5
=> 5
irb> a.methods
=> [:-@, :**, :<=>, :upto, :<<, :<=, :>=, :==, :chr, :===, :>>, :[], :to_int, :coerce, :divmod, :to_s, :to_i, :fdiv, :modulo, :remainder, :abs, :magnitude, :gcd, :integer?, :gcdlcm, :numerator, :lcm, :to_r, :floor, :ceil, :round, :truncate, :rationalize, :to_f, :^, :odd?, :even?, :phase, :imag, :abs2, :arg, :conjugate, :conj, :rectangular]
irb> a.method(:even?).owner
=> Integer
railsでやったら.ownerでNoMethodErrorが出た。なんで?
bundler
can’t find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)
bundlerのバージョン違いで出るエラー。
bunler2系のエラーだそう。
Bundler: An update on the Bundler 2 release
bundler.io
gem.lockファイルに記載のbundled_withのバージョンを確かめるか、以下でバージョンを確認。
cat Gemfile.lock | grep -A 1 "BUNDLED WITH"
あとはバージョンを指定してgemをインストールすればOK
gem install bundler -v '2.0.1'
コメント