1
0

Progate +α メモず 【Ruby】

Last updated at Posted at 2024-01-12

はじめに

Progate楽しいマンです。
最近学んだことリスト【主にCSS】に続き、Rubyをやりました。
今回は1つの記事にまとまった!あと、少し見やすく書けました。(^^)
相変わらずなっがいので、気になった見出しがあれば見てみてください。

メモず

Rubyの"'は区別なし

言語によっては区別あるので……Rubyは緩い方。

コメントは#

シンプルですこ (^^)

余り計算は%でOK

`mod`も好きだけどね

Rubyのputsの挙動一覧

puts "str " int # 間違った構文
puts "str ", int # "str"<br>int
puts "str #{int}" # str int テンプレート記法
puts 'str #{int}' # str #{int} シングルクォーテーション(')だとテンプレート記法と認識しない。

テンプレート記法は"の中に#{}で書くことができる。
文字列と同じ書き方でできる、最高です(^^)
Javascriptでは`の中に${}なので混同しないように注意。

Rubyの変数はvarname =で特定の宣言文はない

変数名はキャメルケースではなくスネークケース

俺のキャメルケースが……

+=は可能

else ifではなくelsif

ちょっとキモい……

倫理演算子は ==, !=, &&, ||

===じゃなくていい!素晴らしい!
or||なので、二個にするの忘れないように。
全部2個だと見た目がそろうのでいいね!素晴らしい設計。

each / for of 文:arr.each do |e|

連想配列は{"key"=>value, ...}or{:key=>value}or`{key:value}

JSと違い、key"で囲わなきゃいけない。keyを文字列にしなかった場合は、変数として扱われる(まじかよ)

key = "name"
hash = {key => "John Doe"}

この場合、hash のキーは "name" の文字列となります

Ruby1.9以降では、以下の構文が導入

hash = {key: value} #キーは:keyシンボル

シンボル:keyと文字列"key"の違いって?

シンボルと文字列の違い
  1. イミュータビリティ(変更不可能性):

    • 文字列: 文字列は変更可能です。例えば、str = "hello" とした後で str[0] = "H" により str"Hello" に変更できます。
    • シンボル: シンボルはイミュータブル(変更不可能)です。一度作成されると、その値は変更できません。
  2. オブジェクトID:

    • 文字列: 同じ内容の文字列でも、それぞれが異なるオブジェクトとして作成されます。つまり、毎回新しいメモリが割り当てられます。
    • シンボル: 同じ内容のシンボルはアプリケーション全体で同じオブジェクトを参照します。これにより、メモリ使用効率が良くなります。
  3. パフォーマンス:

    • 文字列: 文字列の比較は内容を1文字ずつチェックするため、比較に時間がかかることがあります。
    • シンボル: シンボルの比較はオブジェクトIDの比較になるため、高速です。
混同した場合の影響
  • ハッシュのキーとしての使用: Rubyではハッシュのキーとして文字列とシンボルのどちらも使用できますが、これらは異なるキーとして扱われます。たとえば、{ :key => "value1" }{ "key" => "value2" } は異なるキーを持つハッシュです。これらを混同すると、意図しない挙動を引き起こす可能性があります。

  • メモリ使用: 文字列を頻繁に作成すると、同じ内容でも異なるオブジェクトがメモリ上に作成されるため、メモリ使用量が増加します。一方、シンボルは同じ内容であれば同じオブジェクトを再利用するため、メモリ効率が良いです。

  • 変更可能性: 文字列は変更可能なので、アプリケーションの状態を変更する可能性があります。シンボルは変更不可能なので、このような副作用はありません。

Rubyではnilfalse 以外のすべての値は真と評価される

つまり、undefinedが存在しない。
例えば、連想配列の存在しないキーにアクセスした場合、JSだとundefinedを返すが、Rubyだとnilを返す。
豆知識:JSのnull、Rubyのnilfalsyと呼び、falseではないがfalseとして扱われることがある。

&.演算子

Rubyの場合、ハッシュに存在しないキーにアクセスしたときは nil が返されるので、一般的には安全です。ただし、その後に nil に対してメソッドやさらなるキーへのアクセスを試みるとエラーが発生します。したがって、element[:values]nil でないことを確認することは重要ですが、より簡潔に書く方法もあります。

例えば、以下のように &. 演算子(セーフナビゲーション演算子)を使用すると、element[:values]nil の場合には、それに続くメソッド呼び出しが無視されます:

array = [{values: {a: "v", b: "v2"}}, ...]

array.each do |element|
  puts element[:values]&.[](:b) 
  #[](:key)は[:key]のもともとの形。ここではメソッド呼び出しをしている。
end

この場合、element[:values]nil であれば、[:b] の呼び出しは無視され、nil が返されます。これにより、element[:values] が存在しない場合にエラーを防ぐことができます。また、element[:values] が存在していても、それがハッシュであり :b キーが存在しない場合には、やはり nil が返されます。

この方法は、Ruby 2.3 以降で利用可能です。それ以前のバージョンでは、条件分岐を使用してキーの存在を確認する必要があります。

hash[:key]hash.[](:key)の糖衣構文

そうなん!!いわれてみれば確かに🦀

[](:b)[:b] の違い

element[:values]&.[](:b)element[:values]&.[:b] は実質的に同じ動作をします。ただし、&. 演算子を使用してメソッド呼び出しを行う場合、[](:b) の形式を使用することで、element[:values]nil であった場合にメソッド呼び出しを無視することができます。一方で、element[:values]&.[:b] は文法的に不正です。

element[:values]&.[:b] ではなく element[:values]&.[](:b) を使用する理由は、セーフナビゲーション演算子 &. がメソッド呼び出しにのみ適用されるためです。[:b] はハッシュのキーへのアクセスを示すブラケット構文ですが、これを直接 &. と組み合わせることはできません。そのため、メソッド呼び出しの形式 [](:b) を使用します。

Rubyにはfunctionという概念がない!!

すべてメソッドと呼ばれる。

命名規則:真偽値を返すメソッドは末尾に?をつける

negative?など

キーワード引数※超便利!!全オブジェクト指向言語に導入すべき

それに対して、普通のを位置引数と呼ぶ。
キーワード引数は

def method(arg1:, arg2:)
	puts "#{arg1}, #{arg2}"
end

method(arg2:"hoge", arg1:"ruby")
method("ruby", "hoge") #error. キーワード引数は位置引数として呼び出せない。

これで機能する。すごい。
あと、発展形として

def method(arg1, arg2:"arg2!!")
	puts "#{arg1}, #{arg2}"
end

method("ruby", arg2:"hoge") # ruby, hoge
method("ruby") # ruby, arg2!! ※初期値arg2!!が設定されているため
method(arg2:"hoge", "ruby") #error. キーワード引数は位置引数の後。

初期値の設定、キーワード引数と位置引数の混合も可能。
どっちも便利だなあ……
毎回呼び出さない、いわばアディショナルになる引数はキーワードで初期値を設定しておいて、それ以外は位置引数で毎回渡す、ってことが可能

#今日の日付を取得
today = Date.today
#日記を保存する
def diary(title, content, date:today)
	#日記を作成。日付がdate, タイトルがtitle, 内容がcontent
end

#今日の日記
diary("rubyを学んだ", "キーワード引数とか、おもしろいことがいっぱいあった") 
#書き忘れた昨日の日記
diary("CSSを学んだ", "デザインって、やっぱ楽しいなと思った", date:"2024-01-12") 

なお、初期値の設定はJSでもできるようになってたっぽい(ES6)
知らなかった……

function greet(name, greeting = "Hello") {
  return `${greeting}, ${name}!`;
}

console.log(greet("Alice"));          // "Hello, Alice!"
console.log(greet("Alice", "Hi"));    // "Hi, Alice!"

命名規則:クラスは大文字で始める

class Menuてきな

ボクが苦手な「クラス」という概念

@:インスタンス変数

オブジェクトごとに存在する変数

initialize:コンストラクタ

newしたときに実行されるメソッド。rubyではdef initialize

class Person
  def initialize(name, age)
    @name = name  # インスタンス変数の設定
    @age = age    # インスタンス変数の設定
  end

  def greet
    "Hello, my name is #{@name} and I am #{@age} years old."
  end
end

# クラスからオブジェクトを生成
alice = Person.new("Alice", 30)

# オブジェクトのメソッドを呼び出す
puts alice.greet  # => "Hello, my name is Alice and I am 30 years old."

なお、@name = nameself.name = nameどちらでも機能するが、大きな違いがある。

@name = name
  • @name = name は、インスタンス変数 @name にローカル変数 name の値を直接割り当てます。
  • この表現は、Rubyのインスタンス変数に直接アクセスし、値を設定する最も基本的な方法です。
self.name = name
  • self.name = name は、name= という名前のセッターメソッドを呼び出し、そのメソッドを通じて @name インスタンス変数に値を設定します。
  • この方法は、attr_accessor または attr_writer によって自動的に生成されたセッターメソッドを利用します。
  • セッターメソッドを通じて値を設定することで、追加の検証や処理を行うことができます。
どちらを使用するべきか
  • 直接割り当て (@name = name): 値を直接設定するだけの場合、または特別な検証や処理が不要な場合に適しています。
  • セッターメソッド経由 (self.name = name): セッターメソッドに特別なロジック(例えば、検証、変換、ロギングなど)が含まれている場合に適しています。また、将来的にセッターメソッドの挙動を変更する可能性がある場合にも有用です。

attr_accessor:ゲッターとセッターを設定

アトリビュート(属性・プロパティ)へのアクセサを設定する。
具体的には以下の2つ

  • ゲッターメソッド: インスタンス変数の値を取得するメソッド
  • セッターメソッド: インスタンス変数に値を設定するメソッド
class Person
  attr_accessor :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end

person = Person.new("Alice", 30)
puts person.name  # => Alice #ゲッターメソッド
person.name = "Bob" #セッターメソッド
puts person.name  # => Bob 

類似メソッドとして、以下のものがある

  • attr_reader: ゲッターメソッドのみを生成
  • attr_writer: セッターメソッドのみを生成
    なんでわざわざattr_accessorと記述しないと記述しないとアクセスできないの?
    不便じゃない?と思ったキミ!
    危険なのだ!不必要なアクセスはバグの温床なのだ!

インスタンスメソッド

newでインスタンスを作った後に使われるメソッド
インスタンスから呼び出す。当然クラスからは呼び出せない。

class Person
  def initialize(name)
    @name = name
  end

  def greet #インスタンスメソッド
    "Hello, my name is #{@name}"
  end
end

alice = Person.new("Alice")
puts alice.greet  # => "Hello, my name is Alice"

なお、initializeもインスタンスメソッドに属する。ただし直接呼び出すことはできない。

クラスメソッド

クラス自体に属するメソッド。インスタンスからは呼び出せない。
def self.method_nameclass名を用いて定義される。

class Person
  def self.describe #Person.describeでも同じ。ただ、selfの方がクラス名の変更に対応できる。
    "This is a Person class"
  end
end

puts Person.describe # => "This is a Person class"

me = Person.new
puts me.describe  # これはエラーになります

クラシックな例

class MyClass
  @class_instance_var = "初期値"

  # クラスインスタンス変数へのアクセス用のクラスメソッド
  def self.class_instance_var
    @class_instance_var
  end

  # クラスインスタンス変数を設定するためのクラスメソッド
  def self.class_instance_var=(value)
    @class_instance_var = value
  end
end

# クラスメソッドを通じてクラスインスタンス変数を取得
puts MyClass.class_instance_var  # => "初期値"

# クラスメソッドを通じてクラスインスタンス変数を設定
MyClass.class_instance_var = "新しい値"
puts MyClass.class_instance_var  # => "新しい値"

クラスの継承<

class Food < Menuなど

オーバーライド&super

親クラスのメソッドを子クラスで「上書き」すること

class Person
  def initialize(name, age)
    @name = name
    @age = age
  end

  def info
    "Name: #{@name}, Age: #{@age}"
  end
end

class Employee < Person
  def initialize(name, age, job)
    super(name, age)  # 親クラスのinitializeメソッドを呼び出し
    @job = job  # 従業員固有の属性
  end

  def info
    "#{super}, Job: #{@job}"
  end
end

employee = Employee.new("Alice", 30, "Developer")
puts employee.info  # => "Name: Alice, Age: 30, Job: Developer"
#キーワード引数の場合
def initialize(name:, price:, calorie:)
	super(name: name, price: price) #(parent_keyword_arg: child_arg)
	self.calorie = calorie
end

require:インポート文

require "./partsなど。.rb拡張子は省略するのが通例。

Rubyの require メソッドはデフォルトで .rb または .so(またはプラットフォームに応じた適切なバイナリファイルの拡張子)を探します。他の種類のファイルを読み込む場合、特に .js.json などの非Rubyファイルを読み込む場合は、明示的に拡張子を指定する必要があります。

gets.chomp:コンソールからの入力を取得

gets:コンソールを入力待機状態にする
chomp:文字列の末尾にある改行文字(\n\r\n)を取り除く。主に「がぶりとかじる」や「むしゃむしゃ食べる」といった意味で使われる動詞
gets.chomp取得された文字列には、ユーザーがEnterキーを押した際に生成される改行文字(\n)が含まれているため、chompと併せて使用される。

.to_i

おもろい。確かにこの命名でいいよなあ、ってなる。

.to_ffloat
.to_sstring
.to_symsymbol ←初めて見た。文字列に対して使うっぽい。
.to_hhash←すごい。

[["key1", "value1"], ["key2", "value2"]].to_h
# => {"key1" => "value1", "key2" => "value2"}`

追記:extendinclude

モジュールの読み込み方
extendはクラスメソッドとして
includeはインスタンスメソッドとして読み込む

終わりに

久しぶりにコードかけて気持ち良かった……
CSSも楽しかったけど、やっぱ動くのがいいですね。
次はRails!SNSを作れるとのことで、非常に楽しみ。SNSのレイアウトを使って実装したいアイデアもあるので、モチベ高めです。明日から。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0