2019/06/03
clone
ransackを使っていて、p1 = params[:q]
とすると、p1
の値を変えたときにparams[:q]
も変わってしまう。
p2 = params[:q].clone
dup
、clone
は浅いコピー(シャローコピー)と呼ばれる。
配列やハッシュ自体は複製される(違うobjectidで作成される)が、要素までは複製されず
p3 = params[:q].dup
で複製した場合、params[:q][:hoge]の変更に影響を受ける。
まとめると、
params[:q][:hoge] = 'sample text' p1 = params[:q] p2 = params[:q].clone p3 = params[:q].dup p4 = Marshal.load(Marshal.dump(params[:q]))
としたときにparams[:q][:hoge].upcase!
で破壊的な変更を加える。
すると
p1[:hoge] # => SAMPLE TEXT p2[:hoge] # => SAMPLE TEXT p3[:hoge] # => SAMPLE TEXT p4[:hoge] # => sample text
ここは深いコピーであるp4以外変更される。
もうひとつ、params[:q][:hoge] = 'piyopiyo'
としたとき
p1[:hoge] # => 'piyopiyo' p2[:hoge] # => SAMPLE TEXT p3[:hoge] # => SAMPLE TEXT p3[:hoge] # => sampe text
これはp1以外影響を受けない。
そのあと、params[:q][:hoge].downcase!
しても、p2,p3は影響を受けず変わらない。
params[:q][:hoge].upcase!
しても変更があるのはp1だけ。
ちなみにparams[:q][:hogehoge]='fuga'
として新しいいハッシュを追加しても、p1以外には影響しない。
疑問
params[:q]をそのまま変数p1に入れたときは、params[:q][:hoge]の変更がそのままp1に反映される params[:q].cloneをp2に入れたときは、値の代入が影響しない
余談
p2==p3 # => true p2.object_id == p3.object_id # => false p2.equal? p3 # => false
==
は値?だけあってればいいのかな。