エラー: 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 ディレクトリ名
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"
まとめ
- インスタンスメソッドとして使用したい場合は
include
かprepend
- クラスメソッドとして使用したい場合は
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.メソッド
として定義しない
- クラスメソッドを再定義するにはsingleton_classを使用する
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"
- attr_reader
- インスタンス変数の読み取りメソッドを省略したもの
nameメソッドを上書きするのは理解できるが@name
とoriginal_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で再定義したメソッドが優先的に探索される