どぼじょのIT学習ブログ

高専卒土木女子がIT業界を目指してお勉強。

Sinatra でメモアプリ

Sinatra で簡単なメモアプリを作成しました!
課題なのでソースコードは載せられませんが💦💦

目次

1.成果

1-1. スクリーンショット

f:id:mistyrinth:20190418171653p:plain

1-2. 機能

メモを新規作成・閲覧・編集・削除ができます。
トップページにはメモのタイトル一覧が表示されます。(更新順)
メモのタイトルが未入力の場合、自動的にNOTITLEというタイトルになります。

1-3. 構成

データベースを使わず、メモをtxtファイルにして保存する仕組みにしました!
ファイル名にはタイムスタンプを使い、メモごとに固有のファイル名がつくようにしました。
※ファイル名(タイムスタンプ.txt)と、トップページに表示されるメモのタイトルは別物
ディレクトリ構成は以下のとおりです。

memo_app/
-main.rb
-views/
    -top.erb
    -new.erb
    -show.erb
    -edit.erb
-public/
    -style.css
    -favicon.ico
-Gemfile
-Gemfile.lock
-.gitignore

2.学んだこと

2-1. Webアプリの構造

初めてWebアプリを作ったのですが、とっても難しかったです!!😂
Ruby や HTML など個別に基礎をわかっていても、複合的になって難易度がぐっと上がりました。
というかわからないことが多すぎて何がわからないかわからない状態…💀💀
先述のディレクトリ構成についてもそうですが、Web アプリの構造の部分が見えてきたら、自分で考えながら修正したりできるようになりました。

f:id:mistyrinth:20190418174705p:plain

2-2. Methodoverride

HTMLで使えるHTTPメソッドは GET と POST だけみたいです。
PATCH(更新)とDELETE(削除)を使うには Methodoverride というものを使いました💪

使用方法(PATCHの例)
1.main.rbに以下の一文を追加

enable :method_override

2.erb内のPATCHを使いたいフォームを以下のように作成

<form action="/(場所指定)" method="POST">
<input type="hidden" name="_method" value="PATCH">

2-3. TwitterBootstrap

シンプルとはいえ見た目を少しは綺麗にしたかったので、TwitterBootstrapを導入しました!

getbootstrap.com

これを使うとStylesheetファイルを作らなくても、HTMLの class に専用の名前を指定するだけでとても簡単に綺麗なものができます。
詳しくはドットインストールで無料で体験できます😊
Bootstrapの機能以外に細かく指定したいことがあれば、別途CSSファイルを作って読み込むという形にしました。

2-4. favicon

favicon.ico というものを作らないとサーバ側でエラーが出てしまうので、作りました。
作るといってもフリー素材のアイコンをダウンロードしてpublicディレクトリに置き、 ビュー(ERB)のheadタグ内に以下の一文を書くだけです👏超簡単!

<link rel="shortcut icon" href="favicon.ico">

2-5. その他困ったときの解決法

単一のRubyファイルと違って複数のファイルを編集しているため、Webで表示したいものが表示されないときなど、どこが原因か突き止めるのが最初はとても難しかったです。
そこだけ抜粋して動作確認というのもできない場合もありました😅 そんなとき、以下の確認をとるとなんとなく原因が思い当たるようになりました。

  • サーバのログを読む main.rb で puts メソッドを使うとサーバ側コンソールに表示されます。
  • エラーページを最後まで読む GET まではうまくいってるみたいだなーなんてことがたまにわかりました。
  • Chromeの左クリックでページのソースコードを読む ERBで書いたはずのことがちゃんと反映されてないことに気づけました。

SinatraでWebの基本を学ぶ

今回は Sinatra を使って Web の基本を学びます!
Ruby on Rails は機能が多いので、Sinatra からのほうが入りやすいそうです。

目次

1.Sinatraインストール

まず Sinatra をインストールをします。

$ gem install sinatra

f:id:mistyrinth:20190327171239p:plain

同様に、関連 gem もインストールしておきます。

$ gem install sinatra-contrib
$ gem install activerecord

私は既にインストール済みですが、sqlite3を未インストールの場合ここでインストールしておいたほうが良さそうです😐

2.ディレクトリの作成

ここからは以下のサイトを参考に進めていきます!

qiita.com

まずディレクトリを作成します。ここではディレクトリ名はsinatra_sampleとします。
作成したディレクトリに移動して、bundle initを実行します。これにより bundler が使えるようになり、Gemfileというファイルが作成されます💡
f:id:mistyrinth:20190327184053p:plain

Gemfile内には既に数行書かれていますが、以下の1文を追加します。

gem 'sinatra'

f:id:mistyrinth:20190327184937p:plain

続いてgemのインストールを行います💪
f:id:mistyrinth:20190327185107p:plain

3.アプリケーションの作成と起動

試しにRubyファイルを作成します。ファイル名はapp.rbにします。
中身は以下のように書きます✍️
f:id:mistyrinth:20190327185519p:plain

書けたら、bundler で実行します。
bundle exec ruby app.rbとなります!
f:id:mistyrinth:20190327190010p:plain

この状態でlocalhost:4567に接続すると、helloという文字が現れます✨
ローカルホストなのでブログリンクから飛んでも表示されませんが💦
こんなふうになります。

f:id:mistyrinth:20190327190214p:plain

4.sinatra reloader

app.rbの内容を変更してブラウザを再読み込みしても、変更が反映されません。
変更を反映するには、sinatraを再起動する必要があります。
そこで再起動を簡単にするために、 sinatra reloader をインストールします! まず起動中のアプリを閉じ、Gemfileに以下を追加します。

gem 'sinatra-contrib'

追加したら先程と同じく$ bundle installを実行します。
次にapp.rbを編集します。

f:id:mistyrinth:20190327221331p:plain

再びbundle exec ruby app.rbを実行すると、localhost:4567は以下の画面になります!
f:id:mistyrinth:20190327224149p:plain

今後はブラウザの再読み込みで変更が反映されます🎉

5.動かしてみる

先程のapp.rbのコードに3行追加します。path/toとか書いてあるあたりです。
ルーティングを追加しています。
f:id:mistyrinth:20190327225505p:plain

この状態だと、localhost:4567/path/toが以下のように表示されます🙂
f:id:mistyrinth:20190327225727p:plain

次に、静的ファイルを追加します。
ルートディレクトリ配下にpublicディレクトリを作成します。
その中にthis is html file.と書かれたtest.htmlファイルを作成します。
f:id:mistyrinth:20190327230200p:plain

この状態でlocalhost:4567/test.htmlを開くと以下のようになっています👀
f:id:mistyrinth:20190327230309p:plain

更にapp.rbに3行追加します。
f:id:mistyrinth:20190327230525p:plain

この場合、*ワイルドカードで任意の文字列が入ります。
なのでlocalhost:4567/hello/sayakaにアクセスすると、以下のようになります!
f:id:mistyrinth:20190327231138p:plain
sayaka を別の名前にしても同様です。

次はビューを使ってみます。
app.rbにまた3行追加します。見づらくなってきたので、行番号を表示しました😊
16〜18行目のところです。
f:id:mistyrinth:20190327231531p:plain

追加できたら、今度はディレクトリとファイルを作成します。
ディレクトリはviewsで、ファイルはerb_template_page.erbです💡💡
erb_template_page.erbの中身は以下の1行です。
f:id:mistyrinth:20190327232345p:plain

この状態で、localhost:4567/erb_template_pageにアクセスすると、現在時刻が表示されます!
f:id:mistyrinth:20190327232546p:plain

続いて、redcarpet という、Markdownに対応させる gem を対応させます。
Gemfileに1行追加し、$ bundle installを実行します。

gem 'redcarpet'

f:id:mistyrinth:20190327232904p:plain

app.rbに3行追加します。対象箇所だけ抜粋します。
f:id:mistyrinth:20190327233320p:plain

またviewsディレクトリの中にファイルを作成します。 名前はmarkdown_template_page.markdownです。
中身は以下のとおりです😎😎
f:id:mistyrinth:20190327233608p:plain

これでlocalhost:4567/markdown_template_pageを見ると、以下のようになります。
f:id:mistyrinth:20190327234003p:plain
Markdown の見出し#が反映されているようですね👏

先程の erb と markdown を組み合わせてみます。
※ここからリンク先サイトとは少し違います。たぶんリンク先サイトに誤りがあります。
app.rbに以下の3行を追加します。
f:id:mistyrinth:20190328001933p:plain

viewsディレクトリの中にファイルを2つ作成します。
ひとつめはerb_and_md_template_page.erbで、中身は以下のとおりです🙂
f:id:mistyrinth:20190328000559p:plain

ふたつめは同名のmarkdownファイルで、中身は以下のとおりです。
f:id:mistyrinth:20190328001951p:plain

これでlocalhost:4567/erb_and_md_template_pageを見ると、以下のようになっています🎉🎉🎉
f:id:mistyrinth:20190328002036p:plain

Sinatraの基本は以上です!

vimの基本コマンドおさらい

vimについて復習をしたので、まとめです!

目次

1.移動

コマンド 動作
i 挿入モードに切り替え
: コマンドモードに切り替え
v ビジュアルモードに切り替え
escキー ノーマルモードに切り替え
l カーソルをひとつ右へ
j カーソルをひとつ下へ
h カーソルをひとつ左へ
k カーソルをひとつ上へ
G 一番最後の行に進む
gg 一番始めの行に戻る
ctrl + f 画面単位で下に進む
ctrl + b 画面単位で後ろ上に戻る
w 単語単位で下に進む
b 単語単位で後ろ上に戻る
$ 行末へ進む
^ 行頭へ戻る
f 文字 文字のところまで進む
;で次にジャンプ
% 対応する括弧までジャンプ

2.基本操作

コマンド 動作
x 1文字カット
dd 1行カット
3ddなら3行カット
p 貼り付け | 
yy 1行コピー
3yyなら3行コピー
u undo(一つ戻る)
ctrl + r redo(undoの取り消し)
.(ピリオド) 直前のコマンドを実行
:e ファイル名 別のファイルを開く
= インデントを揃える
ctrl + n 変数名、関数名を補完
ctrl+v 矩形選択

3.検索、置換

コマンド 動作
/検索語 検索語を検索
n 下方向に検索
N 上方向に検索
* カーソル位置の単語を下方向に検索
# カーソル位置の単語を上方向に検索
:s/置換前/置換後 1箇所の単語を置換
:s/置換前/置換後/g 行内の単語を置換
:%s/置換前/置換後/g 全体で単語を置換
:%s/置換前/置換後/gc 確認しながら全体置換

4.ウインドウ、タブ分割

コマンド 動作
:sp 上下にウインドウ分割
ctrl+w+w+... 別のウインドウへ移動
:vp 左右にウインドウ分割
:close ウインドウを閉じる
:tabnew 新しいタブを開く
:tabe ファイル名 新しいタブで開く
gt タブの切替
:tabclose タブを閉じる
$ vim -p ファイル名 ファイル名
※ターミナル操作
vim起動時からタブで開く

5.応用

コマンド 動作
gg + V + G + = 全選択でインデントを揃える
:tabdo %s/置換前/置換後 全てのタブで置換
cit テキストを消して挿入モードにする
※解説
c/d/y 中身を削除して変更(change / delete & insert)
i/a 中身か全体か
t/"/)/] タグかクオーテーションか括弧か、など

6.便利な設定

コマンド 動作
:set number 行番号表示
:set nonumber 行番号非表示
:syntax on/off コード色分けon/off
:set tabstop=4 tabキーのインデント文字数を設定
:set ignorecase 大文字小文字の区別をしない
:set noignorecase 大文字小文字の区別をする

楽々ERDレッスン

『楽々ERDレッスン』(翔泳社)を読みました!
データベース設計の本です📖

目次

1.使用書籍

www.shoeisha.co.jp

2.DB設計総論

2-1. 正規化

DB設計において、One Fact in One Place というのが要点になります。
簡単にいうと、重複を排除して、1つのデータの置き場所を1箇所に整理するような感じです。
これを実現するために正規化という手法があります。

2-2. 正規化の手順(例)

商品の伝票を例にした正規化の手順の例です。

  1. 項目と値を全て列挙
  2. 繰り返し部分の切り出し
  3. 従属性の追加
  4. 冗長性の排除

例えばはじめに項目を伝票番号、日付、顧客名、商品名1、単価1、数量1、金額1、合計金額と列挙し、値を全て書き出します。
次に商品名1、商品名2、…など、繰り返すものを切り出します。
従属性の追加とは、商品ごとに単価が決まっている場合、商品名と単価をくっつけることです。
冗長性の排除とは、金額、合計金額は自明であるため削除するといったことです。

また、レコードの中身とは関係なくレコードの存在を表現するために、IDを定義することがあります。

  1. IDの割り付け
  2. ERDで表現

伝票ID、顧客ID、商品IDを定義し、ERD(Entity Relationship Diagram)という図で表現するという流れですが、詳しくは今後勉強です🙂

2-3. キー

キーとは、膨大なデータの中からあるデータを特定するための識別子です。
キーの定義の善し悪しでデータベース設計のクオリティが大きく左右されるそうです🤨
一般的には以下のようなものがあります。

キー 役割
主キー
(primary key)
・候補キーの中から何らかの意味的に選択された、インスタンスを特定可能な識別子
ユニークキー ・エンティティ内のインスタンスをそれぞれに特定可能な識別子
・実装上はユニークインデックス
候補キー ・エンティティ(箱)内のインスタンスをそれぞれに特定可能な識別子の「すべて」
・実装上はインデックス
外部キー
(foreign key)
・エンティティをまたがってのインスタンス同士の関係
・参照整合性制約

3.DB設計の手順

DB設計の手順は以下のとおりです。

  1. 大まかにブロック分けを行う(業務単位か部門単位)
  2. それぞれのブロックごとにイベント系を洗い出す
  3. イベント系に対する正規化を行って、リソース系を洗い出す
  4. リソース系に対する分類の洗い出しを行って、リソース系の正規化を行う
  5. ブロック間でリソース系の統合を行い、さらに正規化を行う
  6. 導出系の整理をして、最終的な正規化を行う

4.感想など

この本とってもわかりやすいです。
最低限SQLの基礎を知っている方向けの本でしたが、語彙が豊富で表現が面白く、知的で、小説を読んでいるようでした!(わたしの語彙力が残念で申し訳ありません)
頭の良い人にやさしく教えてもらっている気分になれるのでおすすめです💪笑

SQLの基本

本日は SQL について勉強します!
データベースについては以前実務でFileMakerを使っていたので、単語が全く分からないわけではないため、テーブルとかの用語は解説を割愛いたします🙇‍♀️

目次

1.SQLとは

SQL(Structured Query Language)とは、データベースを操作するための言語のことです。
以前PostgreSQLというものを学習しましたが、だいぶ忘れています😗笑
SQLには ISO(国際標準化機構)で定められた標準規格があるそうで、ISO に準拠した SQL標準SQLと言います。

2.SQLの分類

SQLは、定義操作制御の3つに分類されます。

2-1. DDL(Data Definition Language)

DDLデータ定義言語です。以下のようなコマンドがあります。

コマンド 機能
CREATE データベースやテーブルなどを作成する
DROP データベースやテーブルなどを削除する
ALTER データベースやテーブルなどの構成を変更する

削除はDELETEではないのですね…😐
DELETEは次に出てくるので間違えないように注意ですね!

2-2. DML(Data Manipulation Language)

DMLデータ操作言語です。以下のようなコマンドがあります。

コマンド 機能
SELECT テーブルから行を検索する
INSERT テーブルに新規行を登録する
UPDATE テーブルの行を更新する
DELETE テーブルの行を削除する

2-3. DCL(Data Control Language)

DCLはデータ制御言語です。以下のようなコマンドがあります。

コマンド 機能
COMMIT データベースに対して行った変更を確定する
ROLLBACK データベースに対して行った変更を取り消す
GRANT ユーザーに操作の権限を与える
REVOKE ユーザーから操作の権限を奪う

3.SQLの書き方

SQLの書き方にはルールがあります。

  • SQL文の最後にセミコロン ; をつける
  • キーワードに大文字/小文字の区別はない
  • 定数はシングルクォーテーション ‘ で囲む

4.操作方法(sqlite3)

わたしのmacbookには sqlite3 がインストールされているので、これを使って操作をしてみます!
(いつかの勉強会でいつの間にかインストールしてたようです笑)

4-1. 接続

データベースに接続します。データベースが無い場合、新規作成になります。
今回はtestという名前のデータベースを作成します!

$ sqlite3 test.sqlite3

f:id:mistyrinth:20190315205802p:plain

4-2. CREATE

テーブルの新規作成をします。
文章で説明するとものすごくわかりにくいと思うので、実際に作ったもの載せます😂
f:id:mistyrinth:20190315220348p:plain
途中で改行を入れたとしても、先程のルールのとおり、SQL文の最後はセミコロン;です。
なのでキャプチャは6行に分かれていますが、SQL文としては1文です👀

CREATE TABLEのあとにテーブル名shopping_listを書き、その後に括弧( )の中に列名、データ型、制約の3セットが並んでいます。
列名はidnamepricenoteの4つがあります。
データ型は以下のように設定できます💡

データ型 意味
INTEGER 整数(小数は入らない)
CHAR 固定長文字列
指定した最大長に満たない場合は後ろを半角スペースで埋める
VARCHAR 可変長文字列
指定した最大長に満たない場合は何もしない
DATE 日付(年月日)

VARCHARTEXTでも良いみたいですが、VARCHARだと最大長がマルチバイト文字に対応するとか、TEXTだと最大長はバイト数で決まるとか違いがあるそうです。
今はどっちでも良いかな…?

制約がNOT NULLの場合、必ずデータが格納されていないといけないという意味になり、無記入ではエラーになります🧐
最後の PRIMARY KEY は、特定のデータを指定するときの主キーになります。 そのため、主キーは重複してはいけません。
例えば「ラーメン」という商品を2つ登録するとしても、1つめのラーメンと2つめのラーメンを見分けるために異なる主キーを使います。
ここではidを主キーとしています✨

4-3. トランザクション

データベースにおけるトランザクション(transaction)とは、簡単に言うとデータベースの複数の操作を一括で更新することです。
先程作った空のテーブルにデータを入れていきます💪💪

BEGIN TRANSACTION;トランザクションを開始します。
その後INSERTなどでデータを触ったら、最後にCOMMIT;で変更を一括で反映させます。
トランザクションの終了はEND TRANSACTION;です👏
もし途中で間違えたら、COMMITではなくROLLBACKを使って変更を破棄します💡
なんとなく感覚的にわかりやすいです〜🐾

4-4. INSERT

トランザクションを行って、INSERTで2行追加しました!
f:id:mistyrinth:20190315222211p:plain
最後にCOMMIT;を行った時点で、データベースに反映されます。
DB Browser for SQLiteというソフトをインストールしているので、視覚的に確認することができます!
f:id:mistyrinth:20190315222324p:plain

4-5. SELECT

SELECTは検索コマンドです。
今作ったtest.sqlite3にはほとんどデータが格納されていませんが、実際データベースは多大なデータを格納します。
この中から検索する時に使うため、重宝されるコマンドみたいです🎉
f:id:mistyrinth:20190315222556p:plain
*を使うと全てを表示してくれるみたいですね〜!

4-6. DELETE

DELETEは行を削除するコマンドです。
先程追加したorangeの行を削除します。
f:id:mistyrinth:20190315223708p:plain
ブラウザで、行が消えているのが確認できます😶
f:id:mistyrinth:20190315223747p:plain

4-7. UPDATE

UPDATEは行を更新するコマンドです。
f:id:mistyrinth:20190315224101p:plain
単価を1.08倍にしました😊
f:id:mistyrinth:20190315224123p:plain

Rubyでwcコマンドを作った

lsコマンドに続き、Rubyでwcコマンドを作りました〜!
課題なのでカンニング防止のためコードは公開できないのですが、学んだことまとめます💪

目次

1.wcコマンドとは

wcコマンドは、指定したファイルの行数・単語数・バイト数を表示してくれるコマンドです🌱
f:id:mistyrinth:20190315193802p:plain
上記のとおり、fileAは7行、6単語、43バイトであることがわかります✨
7行で6単語というのは、最後に空白行があるからです。ややこしくてすみません笑
f:id:mistyrinth:20190315194028p:plain
なお、macのwcコマンドのソースコードこちらです。

2.wcコマンド成果

複数のコマンドライン引数に対応しました🎉
f:id:mistyrinth:20190315192844p:plain

オプションは-l-w-cに対応しました。
f:id:mistyrinth:20190315193003p:plain

標準入力にも対応👏
f:id:mistyrinth:20190315193101p:plain

3.学んだこと

3-1. コマンドライン引数

lsコマンドでもコマンドライン引数は扱いましたが、なんとなくで出来てしまっていました💦
wcコマンドはそうはいかなかったので、以前よりは扱えるようになったと思います。
RubyにはARGVという、コマンドライン引数を配列にしたものがあります。
例えば$ wc file1 file2ならARGV = ["file1", "file2"]となります。

3-2. 標準入力

Rubyには標準入力を扱うための変数があることがわかりました!

docs.ruby-lang.org

$stdinでもSTDINでもどちらでも良いそうです。
配列のARGVと違って変数なので、それ自体が値を持っているのではないことや、標準入力が代入されるということが注意点でした。

3-3. マルチバイト文字の単語数

これが一番苦戦したのですが、マルチバイト文字を含むファイルを指定すると単語数がずれてしまうことがありました…😭
単語数というのは、wcコマンドにおいては空白文字で区切られた文字列の数と定義されています。
man wcに書いてありました👀

A word is defined as a string of characters delimited by white space characters.
White space characters are the set of characters for which the iswspace(3) function returns true.

そしてこの空白文字の定義はiswspace関数が true であることなんです。
更に、iswspace関数が true を返す値というのは以下のとおりです。

- 空白' '
- 改頁 \f
- 改行 \n
- 復帰 \r
- 水平タブ \t
- 垂直タブ \v

ここまでは良いのですが、これらとマルチバイト文字が何の関係があるかというと、マルチバイト文字はバイト文字に変換すると、ノーブレークスペースというのが含まれていることがあるそうです😳
例えば「配列」のの字にノーブレークスペースが含まれます。

text = "配 列"
text.bytes { |b| print "0x" + b.to_s(16) + " "}
#=> 0xe9 0x85 0x8d 0x20 0xe5 0x88 0x97

配 列という文字列に対して、空白で区切った文字列の数を単語数とすると、2単語ですよね🙂
でもこれオリジナルのwcコマンドだと3が返ってくるんです…😖
をバイト文字にすると0xe9 0x85 0x8dで、このうちの0x85が iswspace 関数で true になってしまうからです。
このような目に見えないスペースをノーブレークスペースと言うそうです。
0x20は普通の半角スペースで、改行は0xa0になります。

ノーブレークスペースをカウントするために、マルチバイト文字をバイト文字列に変換し、ノーブレークスペースの数だけ単語数を増やすことになりました。
バイト文字列というのがよくわかっていなかったのですが、先頭の0xは共通みたいです😶
bytesメソッドで文字列をバイトの数値に変換できるので、それを更に16進数に変換し、0xに続けます。
UTF-8 とかの文字コード?もぼんやりとしか分かっていないので、難しかったです〜〜💀💀💀
分かりやすいサイトとかあったら教えてほしいです…。

Rubyの配列コピーの種類

Rubyの配列コピーについて試したので記録です🙌

目次

1. 配列のコピーの種類

配列をコピーすると同じ要素を参照するのか?他方の要素の変更の影響を受けるのか?というのが曖昧だったので、動作を試してみました!
オブジェクトIDはそのままだと桁が大きく読みづらいので、10000で割った余りの数で比較しています。
結果的には以下のような違いがあるみたいでした⛱

コピーの種類 配列のID 要素のID 要素の変更の影響
浅いコピー 異なる 同じ 受けない
深いコピー 異なる 異なる 受けない
代入 ( a = b ) 同じ 同じ 受ける

2.浅いコピー

2-1. コード

org = ["あいうえお", "abcde", "12345"]
puts "org = #{org} (元の配列)"
puts "配列 org ID:#{org.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"

# shallow copy
shal = org.dup
puts "shal = #{shal} (浅いコピー)"
puts "配列 shal ID:#{shal.object_id % 10000}"
puts "要素 shal[0] ID:#{shal[0].object_id % 10000}"

org[0] = "アイウエオ"
puts "org[0]の値を \"#{org[0]}\" に変更"
shal[1] = "ABCDE"
puts "shal[1]の値を \"#{shal[1]}\" に変更"

puts "org = #{org}"
puts "shal = #{shal}"
puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 shal ID:#{shal.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"
puts "要素 shal[0] ID:#{shal[0].object_id % 10000}"
puts "要素 org[1] ID:#{org[1].object_id % 10000}"
puts "要素 shal[1] ID:#{shal[1].object_id % 10000}"
puts "要素 org[2] ID:#{org[2].object_id % 10000}"
puts "要素 shal[2] ID:#{shal[2].object_id % 10000}"

2-2. 結果

f:id:mistyrinth:20190304173243p:plain

3.深いコピー

3-1. コード

org = ["あいうえお", "abcde", "12345"]
puts "org = #{org} (元の配列)"

# deep copy
deep = Marshal.load(Marshal.dump(org))
puts "deep = #{deep} (深いコピー)"

puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 deep ID:#{deep.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"
puts "要素 deep[0] ID:#{deep[0].object_id % 10000}"
puts "要素 org[1] ID:#{org[1].object_id % 10000}"
puts "要素 deep[1] ID:#{deep[1].object_id % 10000}"
puts "要素 org[2] ID:#{org[2].object_id % 10000}"
puts "要素 deep[2] ID:#{deep[2].object_id % 10000}"

3-2. 結果

f:id:mistyrinth:20190304173330p:plain

4.代入

4-1. コード

org = ["あいうえお", "abcde", "12345"]
puts "org = #{org} (元の配列)"

# substitution
sub = org
puts "sub = #{sub} (代入)"

puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 sub ID:#{sub.object_id % 10000}"

org[0] = "アイウエオ"
puts "org[0]の値を \"#{org[0]}\" に変更"
sub[1] = "ABCDE"
puts "sub[1]の値を \"#{sub[1]}\" に変更"

puts "org = #{org}"
puts "sub = #{sub}"
puts "配列 org ID:#{org.object_id % 10000}"
puts "配列 sub ID:#{sub.object_id % 10000}"
puts "要素 org[0] ID:#{org[0].object_id % 10000}"
puts "要素 sub[0] ID:#{sub[0].object_id % 10000}"
puts "要素 org[1] ID:#{org[1].object_id % 10000}"
puts "要素 sub[1] ID:#{sub[1].object_id % 10000}"
puts "要素 org[2] ID:#{org[2].object_id % 10000}"
puts "要素 sub[2] ID:#{sub[2].object_id % 10000}"

4-2. 結果

f:id:mistyrinth:20190304173418p:plain