ナスカブログ

未来の自分へのドキュメント

エラー: Can't create . because there's already a non-empty directory . existing in path. の回避方法

$ docker-compose run --rm front yarn create nuxt-app
:
Can't create . because there's already a non-empty directory . existing in path.

作成しようとしているディレクトリの中にファイルなどが存在するとエラーが表示される
自分の場合はDockerfileが存在していたためエラーがでた

回避方法

$ docker-compose run --rm front yarn create nuxt-app ディレクトリ名 

ディレクトリを作成してそこにnuxt-appを作成する
作成した後にfrontディレクトリに移動する

Ruby 引数について理解する

引数について理解しないとな〜と思いつつ時が流れようやく思い腰を上げる

rubyリファレンスに以下とある

メソッド定義において、仮引数はその種類毎に以下の順序でしか指定することはできません。いずれも省略することは可能です。

  • デフォルト式のない引数(複数指定可)
  • デフォルト式のある引数(複数指定可)
  • *を伴う引数(1つだけ指定可)
  • デフォルト式のない引数(複数指定可)
  • キーワード引数(複数指定可)
  • ** を伴う引数(1つだけ指定可)
  • & を伴う引数(1つだけ指定可)

クラス/メソッドの定義 (Ruby 2.7.0 リファレンスマニュアル)

実引数と仮引数

  • メソッドを定義する時にどのような値を受け取るかはわからないため仮に置いておくということでメソッド定義時の引数は仮引数という
  • 実際にメソッドを呼び出すときは値がわかっているのでその引数を実引数という

定義方法は以下

def メソッド名(仮引数)
  ## 処理 ##
end

メソッド名(実引数)

デフォルト式のない引数(複数指定可)

def hoge(arg)
  arg
end

p hoge('aaa') #=> "aaa"
  • 複数指定
def hoge(arg1, arg2)
  p arg1 #=> "aaa"
  p arg2  #=> "bbb"
end

hoge('aaa', 'bbb')

デフォルト式のある引数(複数指定可)

def hoge(arg = 'fuga')
  arg
end

p hoge(arg1 = 'aaa') #=> "aaa"
  • 複数指定
def hoge(arg1 = 'fuga1', arg2 = 'fuga2')
  [arg1, arg2]
end

p hoge(arg3 = 'aaa', arg4 = 'bbb') #=> ["aaa", "bbb"]
  • 実引数省略
def hoge(arg1 = 'fuga1')
  arg1
end

p hoge #=> "fuga1"

*を伴う引数(1つだけ指定可)

  • *をつけると配列として格納される
def hoge(*arg)
  p arg.class #=> Array
  arg
end

p hoge('aaa', 'bbb') #=> ["aaa", "bbb"]

メソッドの中で*をつける時は注意が必要

def hoge(*arg)
  p *arg
end

hoge('aaa', 'bbb')
#=> "aaa"
#=> "bbb"
def hoge(*arg)
  *arg
end

p hoge('aaa', 'bbb') #=> syntax error, unexpected '\n', expecting '='

デフォルト式のない引数(複数指定可) 2回目

*引数は最後のあまりものをまとめて配列にしてくれるっぽい

def hoge(arg1, *arg2, arg3, arg4)
  [arg1, arg2, arg3, arg4]
end

p hoge('aaa', 'bbb', 'ccc', 'ddd') #=> ["aaa", ["bbb"], "ccc", "ddd"]

*引数を2つ以上記述するとエラーが出る

def hoge(arg1, *arg2, *arg3, arg4)
  [arg1, arg2, arg3, arg4]
end

p hoge('aaa', 'bbb', 'ccc', 'ddd') #=> syntax error, unexpected *

キーワード引数(複数指定可)

  • key: valueの形で渡す
def hoge(arg1: 'fuga1')
  arg1
end

p hoge(arg1: '#fuga') #=> "#fuga"
  • 仮引数と実引数のkeyは一致しないとエラー
def hoge(arg1: 'fuga1')
  arg1
end

p hoge(arg: '#fuga') #=> unknown keyword: :arg (ArgumentError)
  • 複数指定
def hoge(arg1: 'fuga1', arg2: 'fuga2')
  [arg1, arg2]
end

p hoge(arg1: 'aaa', arg2: 'bbb') #=> ["aaa", "bbb"]
  • 実引数省略
def hoge(arg1: 'fuga1', arg2: 'fuga2')
  [arg1, arg2]
end

p hoge(arg1: 'aaa') #=> ["aaa", "fuga2"]

** を伴う引数(1つだけ指定可)

  • **をつけるとハッシュとして格納される
  • ハッシュなのでキーとバリューの形で引数を渡す必要がある
def hoge(**arg)
  p arg.class #=> Hash
  arg
end

p hoge(arg1: 'aaa', arg2: 'bbb') #=> {:arg1=>"aaa", :arg2=>"bbb"}

これもメソッドの中で**をつけて呼び出す時に注意が必要

def hoge(**arg)
  p **arg
end

hoge(arg1: 'aaa', arg2: 'bbb') #=> {:arg1=>"aaa", :arg2=>"bbb"}
def hoge(**arg)
  **arg
end

p hoge(arg1: 'aaa', arg2: 'bbb') #=> syntax error, unexpected **arg
  • **引数を2つ以上記述するとエラーが出る
def hoge(**arg1, **arg2)
  [arg1, arg2]
end

p hoge(arg1: 'aaa', arg2: 'bbb') #=> syntax error, unexpected **arg, expecting & or '&'

& を伴う引数(1つだけ指定可)

  • ブロックの中身はblock.callまたはyieldで実行される
def hoge(&arg)
  arg.call
end

hoge { p 'aaa' } #=> "aaa"
def hoge(&arg)
  yield
end

hoge { p 'aaa' } #=> "aaa"
  • &引数を2つ以上記述するとエラーが出る
def hoge(&arg, &arg2)
  [arg.call, arg2.call
end

hoge { p 'aaa' }, { p 'bbb' } #=> syntax error, unexpected ',', expecting ')'

最後に全ての書き方を詰め込むと以下のように記述できる(褒められたものではない)

def hoge(arg, arg2, arg3 = 'hoge1', arg4 = 'hoge2', *arg5, arg6, arg7, arg8: 'fuga1', arg9: 'fuga2', **arg10, &arg11)
  [arg, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11.call]
end

p hoge('aaa', 'bbb', arg3 = 'ccc', arg4 ='ddd', ['eee', 'fff'], 'ggg', 'hhh', arg8: 'iii', arg9: 'jjj', piyo: 'kkk') { p 'lll' }
#=> ["aaa", "bbb", "ccc", "ddd", [["eee", "fff"]], "ggg", "hhh", "iii", "jjj", {:piyo=>"kkk"}, "lll"]

複数指定できるものは2回ずつ引数を書いている

引数はそれぞれ以下のように対応している

引数 種類
arg, arg2 デフォルト式のない引数(複数指定可)
arg3, arg4 デフォルト式のある引数(複数指定可)
arg5 *を伴う引数(1つだけ指定可)
arg6, arg7 デフォルト式のない引数(複数指定可)
arg8, arg9 キーワード引数(複数指定可)
arg10 ** を伴う引数(1つだけ指定可)
arg11 & を伴う引数(1つだけ指定可)

まとめ

  • *が1つだけの引数は配列、2つの引数はハッシュとして扱う
  • *引数は可変長引数, **引数はオプション引数
  • *引数の後にはデフォルト式のない引数をもう一度書くことができる

ruby tips (include, prepend, extend)

rubyのinclude, prepend, extendについての理解が曖昧だったのでそれぞれの違いをまとめていく

include prepend extend
メソッドの種類 インスタンスメソッド インスタンスメソッド クラスメソッド
メソッド探索 対象のクラスの後 対象のクラスの前 対象のクラスの後

include

module Fuga
  def hello
    p "Hello Fuga"
  end
end

module Fuga2
  def hello
    p "Hello Fuga2"
  end
end

class Hoge1
  include Fuga, Fuga2
  p self.ancestors #=> [Hoge1, Fuga, Fuga2, Object, Kernel, BasicObject]

  def hello
    p "Hello Hoge1"
  end
end

Hoge1.new.hello #=> "Hello Hoge1"
Hoge1.hello #=> undefined method `hello' for Hoge1:Class (NoMethodError)

prepend

module Fuga
  def hello
    p "Hello Fuga"
  end
end

module Fuga2
  def hello
    p "Hello Fuga2"
  end
end

class Hoge3
  prepend Fuga, Fuga2
  p self.ancestors #=> [Fuga, Fuga2, Hoge3, Object, Kernel, BasicObject]
  def hello
    p "Hello Hoge3"
  end
end

Hoge3.new.hello #=> "Hello Fuga"
Hoge3.hello #=> undefined method `hello' for Hoge3:Class (NoMethodError)

extend

module Fuga
  def hello
    p "Hello Fuga"
  end
end

module Fuga2
  def hello
    p "Hello Fuga2"
  end
end

class Hoge2
  extend Fuga, Fuga2
  p self.ancestors #=> [Hoge2, Object, Kernel, BasicObject]
  def hello
    p "Hello Hoge2"
  end
end

Hoge2.new.hello #=> "Hello Hoge2"
Hoge2.hello #=> "Hello Fuga"

まとめ

  • インスタンスメソッドとして使用したい場合はincludeprepend
  • クラスメソッドとして使用したい場合はextend
  • 読み込むモジュールのメソッドを優先して使用したい場合はprepend

Ruby Goldへの道 day15

以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp

15日目 得点 86点/100点中

  • prepend
    • メソッド探索はselfの後に追加される
  • include
    • メソッド探索はselfの前?
module M
  def foo
    super
    puts "M#foo"
  end
end

class C2
  def foo
    puts "C2#foo"
  end
end

class C < C2
  def foo
    super
    puts "C#foo"
  end
  prepend M
  # include M
end

C.new.foo
# C2#foo
# C#foo
# M#foo

# prependをinludeに変更した場合
# C2#foo
# M#foo
# C#foo
  • Refeinment
    • クラスメソッドを再定義するにはsingleton_classを使用する
      self.メソッドとして定義しない
class C
  def self.m1
    200
  end
end

module R
  refine C do
    def self.m1
      100
    end
  end
  # refine C.singleton_class do
  #   def m1
  #     100
  #   end
  # end
end

using R

puts C.m1 #=> 200
  • printは改行しない
begin
  print "liberty" + :fish.to_s
rescue TypeError
  print "TypeError."
rescue
  print "Error."
else
  print "Else."
ensure
  print "Ensure."
end

#=> libertyfishElse.Ensure.
  • module_evalをブロックで定義した定数はモジュール内で定義したことになる
mod = Module.new

mod.module_eval do
  EVAL_CONST = 100
end

puts "EVAL_CONST is defined? #{mod.const_defined?(:EVAL_CONST)}"
#=> EVAL_CONST is defined? true
puts "EVAL_CONST is defined? #{Object.const_defined?(:EVAL_CONST)}"
#=> EVAL_CONST is defined? true

Ruby Goldへの道 day14

以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp

14日目 得点 82点/100点中

  • include, extend
    • includeしたモジュール内のメソッドはインスタンスメソッドとして呼び出すことができる
    • extendしたモジュール内のメソッドはクラスメソッドとして呼び出すことができる
module M
  def class_m
    "class_m"
  end
end

class C
  include M
  # Mモジュールないのメソッドをインスタンスメソッドとして呼び出すことができる
end

p C.methods.include? :class_m #=> false
p C.new.methods.include? :class_m #=> true
p C.new.class_m #=> "class_m"
p C.class_m #=> undefined method `class_m' for C:Class (NoMethodError)
  • lambdaは引数が合っていないとArgumentErrorを返す
  • procは引数の足りない分はnilで補完する
local = 0

p1 = lambda { |arg1, arg2|
  arg1, arg2 = arg1.to_i, arg2.to_i
  local += [arg1, arg2].max
}

p1.call("1", "2")
p1.call("7", "5")
p1.call("9")

p local
#=>  wrong number of arguments (given 1, expected 2) (ArgumentError)
  • Objectクラスにメソッドを定義すると特異クラスでもそのメソッドを利用することができる
class Object
  CONST = "1"
  def const_succ
    CONST.succ!
  end
end

class Child1
  const_succ # "2"になる
  class << self
    const_succ # "3"になる
  end
end

class Child2
  const_succ # "4になる"
  def initialize
    const_succ
  end
end

Child1.new # "4"のまま
Child2.new # "5"になる

p Object::CONST

class Object CONST = "1" def const_succ CONST.succ! end end

class Child1 p const_succ #=> "2" class << self p const_succ #=> "3" end end

class Child2 p const_succ #=> "4" def initialize p const_succ #=> "5" end end

Child1.new Child2.new

p Object::CONST

Ruby Goldへの道 day13

以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp

13日目 得点 72点/100点中

  • 継承
  • moduleの中でクラスを定義するとモジュール::クラスとなる
  • そのクラスを継承するとモジュール::クラスを継承したことになる
class Base
  def name
    p 'Base#name'
  end
end

module Scope
  class Base
    def name
      p 'Scope::Base#name'
    end
  end

  class Inherited < Base # Scope::Baseとして解釈される
    def name
      p 'Scope::Inherited#name'
      super
    end
    p self.ancestors # [Scope::Inherited, Scope::Base, Object, Kernel, BasicObject]
  end
end

inherited = Scope::Inherited.new
inherited.name

#=> "Scope::Inherited#name"
#=> "Scope::Base#name"

nameメソッドを上書きするのは理解できるが@nameoriginal_nameが等しいのがわからん
alias_methodはインスタンス変数も上書きするのか?

class Human
  attr_reader :name

  alias_method :original_name, :name

  # attr_readerを書かない場合、インスタンス変数nameの読み取りメソッドが必要
  # def name
  #   @name
  # end

  def name
    puts @name == original_name # true ..??
    "Mr. " + original_name
  end

  def initialize(name)
    @name = name
  end
end

human = Human.new("Andrew")
puts human.name #=> Mr. Andrew
  • singletonモジュール
    • インクルードするとクラスメソッドinstanceを定義する
    • instanceメソッドを呼び出すとインスタンスを一つだけ返す

ずっとインクルードしたらsingletonメソッドが使えるようになると思ってた。。。

require 'singleton'

class Message
  include Singleton

  def morning
    'Hi, good morning!'
  end
end

p Message.instance.morning #=> "Hi, good morning!"

Ruby Goldへの道 day12

以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp

12日目 得点 68点/100点中

  • { }はdo..endより結合度が高いため実行結果に差が出る。
def m1(*)
  str = yield if block_given?
  p "m1 #{str}"
end

def m2(*)
  str = yield if block_given?
  p "m2 #{str}"
end

m1 m2 do
  "hello"
end
#=> "m2 "
#=> "m1 hello"

m1 m2 {
  "hello"
}
#=> "m2 hello"
#=> "m1 "
  • class内でusing モジュールを使用してもエラーにならない
  • スコープ外は無効になる
class C
  def m1
    400
  end
end

module M
  refine C do
    def m1
      100
    end
  end
end

class C
  using M
  # Mモジュール有効化
end
# スコープ外なのでMモジュールは無効

puts C.new.m1 #=> 400
  • モジュールをincludeしたら今いるクラスの真上に入る
  • メソッド探索は今いるクラスになかったらincludeしたモジュールに探索にいく
module M
  def method_missing(id, *args)
    puts "M#method_missing"
  end
end
class A
  include M
  def method_missing(id, *args) # これをコメントアウトするとMモジュールの#method_missingが呼ばれる 
    puts "A#method_missing"
  end
end
class B < A
  class << self
    def method_missing(id, *args)
      puts "B.method_missing"
    end
  end
end

B.new.dummy_method #=> A#method_missing
  • Refinementで再定義したメソッドの探索は優先的に行われる
  • usingの後でクラスを再オープンしてもrefineが先に探索される
class C
  def m1
    200
  end
end

module R
  refine C do
    def m1
      300
    end
  end
end

using R
# Rモジュール有効化

class C # クラス再オープン
  def m1
    100
  end
end

puts C.new.m1 #=> 300
# Refinementで再定義したメソッドが優先的に探索される