preztoで快適ターミナル生活

システム事業部の五十島です。

現在お使いのシェル環境はどんな感じでしょうか?
以下のようにデフォルトをそのまま使用していませんか?

f:id:zenet-tech:20191209114755p:plain

シェル環境を快適にしたいけど、設定がよくわからない・めんどくさい人に朗報です。
必要な設定をほぼ自動的に行なってくれるツールがあります。
GitHub - sorin-ionescu/prezto: The configuration framework for Zsh こちらを使えばお手軽に、素敵zsh環境を構築することができます。

f:id:zenet-tech:20191209115143p:plain

上記画像は一例ですが、git管理をしているディレクトリだとブランチ名が出たり、lsでファイルの種類ごとに色をつけてくれたり・・・様々な設定を含んだ設定ツールになります。

1. 準備

zsh のバージョンが4.3.11以上かを確認しましょう。 以下のコマンドで確認できます。

$zsh --version
zsh 5.7.1 (x86_64-apple-darwin17.7.0)

4.3.11未満の人はzshのバージョンをあげてください。 そもそもzshが入っていない人はインストールをしましょう。(apt-get、yam、brewなどのパッケージ管理ツールで)

2. Preztoの設定

Preztoはgithubからクローンしてきます。 以下のコマンドを実行すると、ホームディレクトリーに .zprzeto ディレクトリが作成されます。

$ git clone --recursive https://github.com/sorin-ionescu/prezto.git “${ZDOTDIR:-$HOME}/.zprezto”

以下を実行して、設定ファイルを作成ます。

$ setopt EXTENDED_GLOB
for rcfile in “${ZDOTDIR:-$HOME}“/.zprezto/runcoms/^README.md(.N); do
 ln -s “$rcfile” “${ZDOTDIR:-$HOME}/.${rcfile:t}”
done

初期のシェルをzshに変更して、新しくターミナルを立ち上げると、いい感じになっています。

$ chsh -s /bin/zsh

3. カスタマイズ

表示のカスタマイズ

表示タイプはデフォルトで色々用意されています。 以下のコマンドを実行すると、一覧で表示されます。

$ prompt -l
Currently available prompt themes:
agnoster cloud damoekri giddie kylewest minimal nicoulaj paradox peepcode powerline pure skwp smiley sorin steeef adam1 adam2 bart bigfade clint default elite2 elite fade fire off oliver pws redhat restore suse walters zefram

以下のコマンドで表示を変更できます。

$ prompt -s cloud

f:id:zenet-tech:20191209120329p:plain

今回は「cloud」に変更してみました。 ただし、新規のターミナルを立ち上げたり、ターミナルを終了するともとに戻ってしまいます。

永続的に使用したい場合は、 ~/.zpreztorc に変更を加えましょう。 100行目あたりの以下に好きな表示タイプ名を入れて保存してください。 次回起動時から表示設定が変更されています。

# Set the prompt theme to load.
# Setting it to 'random' loads a random theme.
# Auto set to 'off' on dumb terminals.
zstyle ':prezto:module:prompt' theme '表示タイプ名'

便利な設定をしよう

preztoはよく使われるコマンドの保管やエイリアス設定なども準備されています。 ~/.zpreztorc にどんどん追加して、好きにカスタマイズしていきましょう。 一覧は以下を参照にしてください。 prezto/modules at master · sorin-ionescu/prezto · GitHub

私は以下のように設定を入れており、git、dockerなどは個人的に入れておくことをおすすめします。
rubyrailsなどは開発で使用しているので入れているという感じです。お使いの開発言語に合わせて、カスタマイズしてみましょう。

 # Set the Prezto modules to load (browse modules).
 # The order matters.
 zstyle ':prezto:load' pmodule \
   'environment' \
   'terminal' \
   'editor' \
   'history' \
   'docker' \
   'directory' \
   'spectrum' \
   'utility' \
   'completion' \
   'git' \
   'osx' \
   'rails' \
   'ruby' \
   'ssh' \
   'prompt'

preztoで快適ターミナル生活はじめてみませんか?

HTML5のdatalistを使って、IE11で部分一致させる。

システム事業部の三浦です。 HTML5で追加された、datalistのちょっとしたクセについて紹介したいと思います。

TL;DR

IEでdatalistを部分一致で引っ掛けたい場合は、
datalist-polyfillを利用すると簡単

本題

HTML5より導入された、inputのlist属性とdatalistタグを利用すると、簡易的にサジェスト機能を実装できます。

datalistのリファレンス

とっても便利な機能なのですが、困ったことにブラウザ毎で仕様が微妙に違うのというクセがあります・・・

何が違うのかというと、前方一致タイプと部分一致タイプに分かれます。

前方一致

部分一致

確認用に以下のhtmlを用意しました。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Datalist</title>
  <style>
    html { font-family: meiryo; }
  </style>
</head>
<body>
  <h2>Datalist確認</h2>
  <input type="text" list="test">
  <datalist id="test">
    <option value="ラーメン">
    <option value="とんかつ">
    <option value="かつ丼">
    <option value="うどん">
    <option value="ステーキ">
  </datalist>
</body>
</html>

リストが表示されている状態(IE11で確認)
f:id:zenet-tech:20191008195310j:plain

また、この状態でと入力すると以下の様な結果となります。 f:id:zenet-tech:20191008195424p:plain

IEは前方一致、chromefirefoxは部分一致となっていますね。

これを解決するためにサジェスト系のライブラリを利用するといったやり方もありますが、
リッチなUI・機能はいらなかったり、手っ取り早くやりたいという時に便利なのがこれです。

datalist-polyfill

※色々な導入方法がありそうですが、簡易的に利用したい場合は、datalist-polyfill.js または datalist-polyfill.min.jsのファイルだけをダウンロードしてください。今回はファイルダウンロードで試しています。

これはもともとPolyfill(ポリフィル)と言われる類のもので、

ポリフィルとは、最近の機能をサポートしていない古いブラウザーで、その機能を使えるようにするためのコードです。大抵はウェブ上の JavaScript です。

https://developer.mozilla.org/ja/docs/Glossary/Polyfill より引用

基本的な使い方としては、未対応のブラウザで同等の動作をさせる(今回はdatalist) ためのスクリプトですが、すでに対応されているのIEの動作を変更することができます!

先ほどダウンロードしたdatalist-polyfillのjsファイルを対象HTMLに読み込みます。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Datalist</title>
  <style>
    html { font-family: meiryo; }
  </style>
  <script src="js/datalist-polyfill.min.js"></script> -----追加
</head>
<body>
  <h2>Datalist確認</h2>
  <input type="text" list="test">
  <datalist id="test">
    <option value="ラーメン">
    <option value="とんかつ">
    <option value="かつ丼">
    <option value="うどん">
    <option value="ステーキ">
  </datalist>

</body>
</html>

例では今回は以下の様なディレクトリ構成を取っています。

index.html
- js
  - datalist-polyfill.min.js

これで以下の様な感じになります。(IE11で確認)
f:id:zenet-tech:20191008195748j:plain

これで、簡単に部分一致に統一することができました!!

以上です。

Railsを3.2系から5.0系にマイグレーションした時の経験談等

初めまして、システム事業部の坂本です。

以前、Railsマイグレーション(バージョンアップ)業務を担当したことがありました。 その際Railsのバージョンアップに伴い、「バージョンを上げると使えなくなる記述」が非常に多く骨が折れた記憶があります。 自身の備忘録も兼ねて、主にこの記事では以下3点にフォーカスを当ててRailsマイグレーションに関して書いて行きたいと思います。

  • ステップ1:そもそもマイグレーションってどうやったの?
  • ステップ2:修正が必要な個所を洗い出してみる
  • ステップ3:実際に修正してみる(具体例有)

マイグレーション業務に関わる予定がある方でも無い方でも、最後まで見て頂ければ幸いです。 「そんな記述が昔は出来たんだ」「あのバージョンでこの機能はまだ実装されてなかったんだ」という発見があって、ちょっと面白いと思います。


ステップ1:そもそもマイグレーションってどうやったの?

根本的な話からです。大まかに説明すると、私が担当した際はRailsマイグレーション作業を以下の流れで行いました。

  1. Gemfileを修正し、bundle install等でRailsのマイナーバージョンを1段階上げる
  2. ソースを修正する
  3. アプリを動かして、一通りの機能を動かしてみる
  4. 修正が不十分であればアプリが落ちるので、必要に応じて更に適宜修正
  5. 全ての修正が完了したら1.へ戻り、目的のRailsバージョンまで繰り返す

上記は飽くまでも一例ですが、基本的には「1段階上げて修正、完了したらまた1段階上げて修正、完了したらまた1段階……」という風に、1ステップずつ作業を行うのが適切です。*1 いきなりRails3.2系からRails5.0系まで上げる、みたいなことをすると多分詰みます。(経験談) 慌てず1段階ずつ行きましょう。

Gemfileの修正について

Gemfileを開いて、railsに対応するバージョンを上書きします。 ここで、例えばrailsを「4.0」と指定すれば「actionmailer」「activemodel」「activesupport」等、Railsのコアライブラリも「4.0」まで上がります。

Gemによっては「actionmailer4.0に対応しているバージョンはX.X.Xから」「rails4.0に対応しているバージョンはX.X.Xから」という風に指定があるため、 bundle installのエラーやRubyGems*2を参考にしながら、適切なバージョンまで必要なGemのバージョンを上げていきます。

ステップ2:修正が必要な個所を洗い出してみる

さてソースコード修正開始の前に、下準備から行きましょう。いざとやろうとしても、闇雲にやると後で良く分からなくなってしまいます。 まず全体を通して、以下の記述3点は後程修正が必要になる可能性が非常に高いです。

  • モデルに対して検索・更新・削除等が行われる記述(特にwhereメソッドを利用していない箇所)
  • Gemファイルに依存する記述(バージョンアップで記述が変わるGemもある)
  • コントローラー、モデルに対するオプション全般

そしてRails3.2系から5.0系への大幅なマイグレーションを行った中で、 ソース修正時のメインとなったのは大きく分けて以下の3通りでした。

  • find(3.2→4.0へアップグレード)
  • updated_all、Strong Parametersへの対応(4.0→4.1へアップグレード)
  • validate全般(4.2→5.0へアップグレード)

間違いなく3.2から4.0に挙げた際の「find」の修正が一番の壁でした。 マイグレーション作業の4割近くはこのメソッドに対する対応だった記憶があります。

勿論上記以外にも修正すべき場所はまだありますが、少なくともここまで私が言及した内容に関してはマイグレーション作業の中で修正が必要になると思われます。 修正が必要なファイル・対応行を一通り書き留めて、後で修正が完了したか確認出来る簡易的なチェックリストを用意しておきましょう。

ステップ3:実際に修正してみる(具体例有)

さて、ここからが本題です。実際にソースコードを修正するとどうなるのか?をコメントと共に記載します。 特に説明が無い限り、以下の通りに記述していきます。

修正前

↓

修正後

修正した個所は沢山ありましたが、今回はその中でも特に印象に残った以下4点をご紹介します。

  • find
  • update_all
  • validate全般
  • Strong Parameter (Rails3系からRails4系)

「find」を修正してみる

基本的な書き換え

User.find(:all, :conditions=> "postal_code=1234567 and gender=0", :order => "name")

↓

User.where(postal_code: 1234567, gender: 0).order(:name)

マイグレーション作業でまず一番最初に驚いた記述がこれでした。Rails3.2系では、findメソッドの中に検索条件・Order条件等を一通り入れることが出来たのですね……

しかし今のRailsではそんなことは出来ませんので、シンプルにwhereメソッドやorderメソッドを利用した記述に変更しましょう。

条件に対する1件目のみ取得

User.find(:first, :conditions=> "name='ゼネット太郎'")

↓

User.find_by(name: 'ゼネット太郎')

先程との差異は「find(:all, ......)」だったのが「find(:first, ......)」になっているところですね。 検索結果の1件目のみ取得したいのであれば、「find_by」が利用できるのでそちらを使用します。

「update_all」を修正してみる

User.update_all("first_name= '田中'", "first_name= '山田'")

↓

User.where(first_name: '山田').update_all(first_name: '田中')

やりたいことはどちらも「苗字が'山田'のユーザ全員の苗字を、'田中'に変更する」です。 以前までは「update_all(更新内容, 条件式)」を利用して、条件式に該当するデータ全てを更新することが出来ましたが現在はupdated_allに引数を2つ以上持たせることは出来ません。 そのため、「where(条件式).update_all(更新内容)」に書き換えます。

余談ですが、修正前をよくよく見てみるとSQLっぽいですね。 「修正前はUPDATE users SET first_name='田中' WHERE first_name='山田';を取り合えずRailsで実装してみて、修正後はよりRailsらしく分かりやすい実装にしてみた」という印象を受けます。

validate全般を修正してみる

だいたい修正の方法が同一なので、まとめて4パターンのみ記載します。

ユーザの名前の長さを最大10文字までにする

validates_length_of :name, :maximum => 10

↓

validates :name, length: { maximum: 10 }

ユーザの年齢は整数のみ許可する

validates_numericality_of :age, :only_integer => true

↓

validates :age, numericality: { only_integer: true }

ユーザの名前は必須とする

validates_presence_of :name

↓

validates :name, presence: true

ユーザの月収は数字のみ許可する

validates_numericality_of  :salary

↓

validates :salary, numericality: true

ここまで、修正方法4パターンを紹介しました。何となく法則性があるのが見て取れると思います。 他にもフォーマットの修正・ユニークの設定等もありますが、基本的には以下の2パターンで修正することが出来ます。

validates_XXXXXXXX_of :カラム名, :オプションキー => オプション値

↓

validates :カラム名, XXXXXXXX: {オプションキー: オプション値}
validates_XXXXXXXX_of :カラム名

↓

validates :カラム名, XXXXXXXX: true

Strong Parametersへの対応(Rails3系からRails4系)

Strong Parametersを大まかに説明すると、ユーザからは特定の項目のみ更新可能にしてセキュリティを強化する仕組みです。ですが、Strong ParameterはRails4系から実装されたものでありRails3系では無かった機能となります。 そのため、Rails3系からRails4系にアップグレードした際、必要であれば対応を行って下さい。

長くなるためここではStrong Parametersに関する言及は行いませんが、詳しくはRuby on Railsガイドのこちらの記事をご確認下さい。

Action Controllerの概要 4.5 Strong Parameters | Railsガイド


所感など

さて、ここまでRailsマイグレーション作業に関して色々書きましたが、もっと書こうと思うと長くなりすぎてしまうので今回はこの程度に収めておきます。

この記事に記載したソースコードのBefore→Afterを改めて見ると、全体的にスッキリして読みやすくなっている印象を受けました。 特にバリデーションはただ単純にスッキリしているだけではなく、実装のしやすさも変わっていると思います。 例えば、実際に「ユーザの名前は必須かつユニークで、最大10文字まで可能」というバリデーションを実装しようとするとRails3系までの記述・Rails5系からの記述ではこのように変わります。

validate_presence_of :name
validate_uniqueness_of :name
validate_length_of :name, :maximum => 10

↓

validates :name, presence: true, uniqueness: true, length: {maximum: 10}

上記のBefore→Afterを見ていると、Rails5の方が文字数も少なくスッキリまとまっていて、パッと見た時に意味が分かりやすい印象を受けるのではないでしょうか。

Railsに限らず、様々な言語でバージョンアップに伴う細かい記述方法の変更があると思われますが、「何故この記述に変更になったのだろうか?」「変更されたことで何かメリットはあるのだろうか?」と考えてみると、ちゃんとした意味があることに気づけて面白いと思いました。


マイグレーションの作業は想像以上に大変だと思いますので、慌てず計画的にやっていきましょう!

最後まで見て頂き、ありがとうございました。

SECCON Beginners ctf 2019 writeup

初めましてシステム事業部の石黒です。

SECCON Beginners2019に参加しました。
解くことができた問題について、どのように解いたかを備忘録がてら残したいと思います。 今回が初参加であり、筆者の業界歴も浅いため、ビギナー目線の記事になることをご承知おきください。

SECCON Beginnersとは

SECCON Beginnersというのはその名の通り、初心者向けのSECCONになります。
(そもそもSECCON is 何?という人はこちら)

今回のSECCON Beginnersは、CTF(Capture The Flag) 形式で行われました。
CTFでは、参加者が様々な攻撃を仕掛け、問題のどこかにあるflagを探し出すことが目的となります。
flagは ctf4b{XXXX}の形式で、暗号化されたりして隠されています。

問題

問題は[Crypto, Pwn, Reversing, Web, Misc]の5種類に分けられており、それぞれ4問ずつあります。
私が解くことができたのは、この内Web系の問題2問になります。

なお、残念ながら全問題についてはすでにサイトが閉じてしまっているため見ることができません。

[warmup] Ramen

warmupということで、一番簡単なものになります。
しかし、初参加の私にはハードでした。

まず、戸惑ったのは問題文です。
問題文は以下のようなものでした。

ラーメン
(url省略)



お わ か り い た だ け た だ ろ う か



他の問題もそうですが、問題文なんてものはありません。SECCONの洗礼を受けました。
なにがなにやらわからないので、とりあえずリンクを踏んでみました。

すると、リンク先はどうやら簡易的なWebサイトのようでした。
サイト内に検索フォームがあるので、sqlインジェクションにあたりをつけてflagを探すことに。

sqlインジェクションについてgoogle先生に聞きながら試すうちに、
どうにか以下のUNION句でテーブル一覧を取得できるところまでたどり着くことができました。

 'UNION SELECT table_name, GROUP_CONCAT(column_name) FROM information_schema.columns GROUP BY table_name -- 

テーブル一覧を取得してみると、flagテーブルがあったので、
今度は以下のUNION句でflagテーブルのデータを取得し、無事flagを見つけました。

 'UNION SELECT flag, flag FROM flag --  
 => ctf4b{a_simple_sql_injection_with_union_select}

ここまで一時間半程度掛かりました。。

katsudon

問題文を見てみると、何やら怪しい文が

Rails 5.2.1で作られたサイトです。  
(url省略)
クーポンコードを復号するコードは以下の通りですが、まだ実装されてないようです。
フラグは以下にあります。 
(url省略)

Rails 5.2.1とわざわざバージョンが書いてあるため、 脆弱性のバグをつくものかと思いましたが、結局わからなかったので、断念。

別の方法を探すため、サイト上に示されている、以下の暗号化されたflagの文字列の複合を試みる方針に。

BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU--0def7fcd357f759fe8da819edd081a3a73b6052a

サイトのRailsコードが公開されていたので、MessageVerifierによって文字が作成されていることはわかりました。 しかし、secret_key_baseがわからないため、複合できそうにない。。。

どうしようかとコードを追っていくうちに、文字列が以下のようにして生成されていることがわかりました。

 "#{data}--#{generate_digest(data)}"

後ろはただのハッシュなので、--以前に対して複合してあげれば行けそう?と思い、 rails consoleで以下を叩くと、

Marshal.load(::Base64.strict_decode64("BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU"))
=> "ctf4b{K33P_Y0UR_53CR37_K3Y_B453}"

flagを取得できました。

この問題も一時間半程度掛かりました。

気づいた方もいるかもしれませんが、上でやっているのはbase64で複合しているということなので、 rails consoleでこんなコードを叩く必要もなく、もっと簡単に解けます。。。 base64の文字列に慣れている方は一瞬だったかと思います。

(補足) 実はこれらの解き方は運営側としては意図していないものだったらしく、
改めてkatudon-okawariとして修正版の問題が出題されました。

そしてこのkatudon-okawariの解き方は、
Rails脆弱性のバグを利用し、secret_key_baseを盗るというもののようです。。。
当初このアプローチをしていただけに、非常に悔しい。。。

まとめ

というわけで、初めてSECCON Beginnersに参加したわけですが、
自身の知識・技術不足を痛感でき、非常に良い刺激になりました!

次はweb以外の問題も解けるように力を付けたいです。

RubyKaigi2019参加レポート

システム事業部の辻本です。RubyKaigi2019に参加してきたのでその感想を書きたいと思います。

参加経緯

自己紹介

  • 入社2年目
  • Ruby歴 約1年
  • Ruby on Railsで社内向けシステムを作っている

…と2018年に入社してそこから業務でRubyを始めたので、まだまだRuby(というかプログラミング)の初心者です。そこで研修も兼ねてRubyKaigi2019へ参加しました。

ちなみにこのRubyKaigi2019への参加、なんと会社から旅費とRubyKaigi参加チケット代を出してもらいました!ありがとうございます!Rubyを始めたばかりで行くかどうか迷っている身にはとても嬉しい援助ですね!

RubyKaigi Silverスポンサー

しかも今回、弊社はSilverスポンサーとしての参加です!🎉
ゼネットのロゴが右下の方に確認できます! f:id:zenet-tech:20190425202001j:plain

RubyKaigi2019

場所:福岡🍜(福岡国際会議場)
日程:4/18-4/20

空港付近 f:id:zenet-tech:20190425201509j:plain 福岡国際会議場 f:id:zenet-tech:20190425201825j:plain 入口 f:id:zenet-tech:20190425201853j:plain

RubyKaigi2019はざっくり説明すると世界中のRubyistが集まってRubyについて話し合う…というものです。セッションと呼ばれるプレゼンのようなものを聞くのが大半ですがパーティなども開かれます。かたい雰囲気ではなく終始和やかです。「遊び」もたくさんあってとても楽しいです。

Sushi🍣 f:id:zenet-tech:20190425201938j:plain

セッション

正直に言うと、分からない事だらけでした😇

Rubyの知識が足りないな~とひしひしと感じました😇😇

次期バージョンのRubyの機能についてどうするか冗談も交えながら話していたりして、「Rubyってこの目の前にいる人達がつくってるんだなあ」と感じました。

また、「Rubyでこういうモノを作りました」という発表もありました。すごい。自分も作りたい。そう思わされました。

ブース

会場ではRubyを使っている様々な企業がブースを開いています。各企業のシステムについて知ることができたり、社員の方と直接お話ができたりします。

また、各ブースではノベルティを配っており、とても楽しいです。貰い過ぎには注意しましょう。自分は帰りの荷物がパンパンになりました…

まとめ

今回、ド素人な自分がRubyKaigi2019に参加したわけですが、やっぱり難しくて分からない話がほとんどでした。じゃあ、何も得たものが無かったのかと言われるとそうではありません。

ありがちですが、やる気が出ました。

会場を見渡して目に映る人たちみんなRubyが好き(多分)。その事実がまず驚きでした。こんなにRubyistっているんだ…しかも世界中にまだまだいる…と。自分はこういうイベントに参加するのが初めてで、基本的に実際に会うRubyistプログラマは社内くらいだったというのもあり、かなり衝撃でした。

しかもセッションではワクワクするような話がたくさんされる(分からないことばかりでしたが!すごいのは分かる!)。

たくさんの刺激を貰いました。

今度参加する時は少しでも理解できる話が増えるよう、がんばります💪😤

【Javascript】オブジェクト配列のコピーに関する注意点

こんにちは。システム事業部の鈴野と申します。

今回は、JavaScriptの業務中コーディングした際の問題について、備忘録的としてまとめた内容を掲載したいと思います。

弊社でもフロント側の開発を扱う業務の中でJavaSciptを扱います。 今注目のフレームワーク「React」「Vue.js」についても積極的に活用しております。 JavaScriptに限らず、プログラム言語において「配列」はあらゆる場面で使用しますが、扱う中で苦戦した経験があったのが「配列のコピー」。

プログラムにおけるコピーには以下の2つがあります。

○シャローコピー →コピー元のオブジェクトとコピー先のオブジェクトがメモリ上の同一データを参照する。 いわゆる「参照渡し」で、コピー先に変更があればコピー元にも反映される。

○ディープコピー →オブジェクトとメモリ上のデータの両方がコピーされるため、コピー元とコピー先は別のデータとなる。 コピー先の変更はコピー元に反映されない。

例えばオリジナルの配列をコピーし、表示用に加工を行う配列を作る場合、もし表示用配列がシャローコピーの場合 オリジナル配列が上書きされてしまいます。

コピーに関するJavaScriptの基本文法もどんどん対応されているようで、有名なのがES6で追加さえたObject.assign()。

 const assigned = Object.assign(, [ 1, 2, 3, 4, 5, 6 ]);

上記はシンプルな配列ですが、例えば以下のような場合はどうでしょうか。

 const complex= [

  { id: 1, array: [ 1, 2, 3, 4, 5 ,6, 7 ] },

  { id: 2, array: [ 11, 12, 13, 14, 15 ,16, 17 ] },

  { id: 3, array: [ 2, 1 ] },

  { id: 4, array: [ 8, 9, 10, 11, 12 ] },

  { id: 5, array: [ 0, 1, 2, 3, 4, 5 ] },

 ]

Object.assign()は第一引数にを渡すことで第二引数以降の内容を元とした新しい配列を生成しますが 動きとしてはシャローコピーであるため、トップ階層に配列要素がある場合は問題ありませんが complexのようなネストとなると対応し切れません。 ReactReduxのような、新規オブジェクト生成を多用する開発では注意が必要です。

現状対応では「JSON.parse()」を使用するのが簡単な対応と思われます。

const deepCopy = JSON.parse(JSON.stringify(complex));

また、jQueryを使える場合はjQuery.extend()の使用も有用なようです。 ただし、上記のような数値、文字列、配列ではコピーされることを確認できていますが、 配列にDate、functionなどが存在する場合は除去されてしまうようです。 配列内容によって使えない機能であるということにご注意ください。

今後もゼネットでは、上記のような言語関連の独自概念についてより良い対策を考え 共有していけるよう努めてまいります。

Ruby技術者認定試験 Goldを受験しました

はじめまして。システム事業部の天野と申します。

Ruby技術者認定試験Gold(Ruby Association Certified Ruby Programmer Gold version 2.1)を先月受験しました。結果は合格でした!!! 今回は私の受験体験記です。

プロフィール

  • 文系出身
  • 入社2年目
  • Ruby歴約2年
  • Ruby技術者認定試験Silverは2年前に取得

勉強方法

問題集1周目は、1問ずつ解き、答えを確認しました。
2周目は10問ずつなど1回に解く問題を増やしました。
3周目以降は本番同様50問ずつ解き、点数を出すようにしました。
答えを見て納得できなかったものに関して、下記の「使った参考書、HP」の該当項目をチェックします。
そして実際にコンソールで実行してみました。(値を変えたりもしました)

使った参考書、HP

勉強期間

  • 2週間
  • 1日2時間程度

学習のポイント

学習のポイントをいくつか紹介します。

・ メソッドの可視性

privateメソッドについてです。
privateメソッドは外部から呼びだすことが基本的にはできませんが、
サブクラスからスーパークラスのprivateメソッドの呼び出しは可能です。

  class A
    private
    def hoge
      "private A hoge"
    end
  end

  class B < A
    def fuga
      hoge
    end
  end

  B.new.fuga
  # 実行結果
  #=> "private A hoge"

またsuperで親クラスの同名メソッドを呼び出しする際も同様に呼び出せます。

  class A
    private
    def hoge
      "private A hoge"
    end
  end

  class B < A
    def hoge
      super
    end
  end

  B.new.hoge
  # 実行結果
  #=> "private A hoge"

・定数の定義について

rubyでは定数(アルファベット大文字で始まる識別子)を定義することができます。
ただし、メソッド内で定義することができないので注意が必要です。

  def a
    CONST = "AAA"
  end

  #=> SyntaxError: (eval):3: dynamic constant assignment
    CONST = "AAA"
          ^

・lambdaとProcの動きの違い

lamdaとProcには挙動が異なる点があります。
以下の2つをしっかり押さえておくことがポイントです。

returnした後の挙動

lambdaの場合、callで呼び出した後の処理も実行されます。

  def lambda_method
    lambda = lambda { return p "return lambda method"}
    lambda.call
    p "lamda method end"
  end

  lambda_method
  #実行結果
  "return lambda method"
  "lamda method end"

Procの場合、callで呼び出した後の処理は実行されません。

  def proc_method
    proc = Proc.new { return p "return proc method"}
    proc.call
    p "proc method end"
  end

  proc_method
  #実行結果
  #=> "return proc method"

引数の扱い

lambdaの場合、引数に過不足があるとArgumentErrorが発生します。
lambdaの方が引数の数に関して厳密です。

  lambda = -> (arg1, arg2) { p "#{arg1}, #{arg2}" }
  lambda.call(1)
  #実行結果
  #=> ArgumentError: wrong number of arguments (given 1, expected 2)

  lambda.call(1, 2)
  #実行結果
  #=> "10, 11"

  lambda.call(1, 2, 3)
  #実行結果
  #=> ArgumentError: wrong number of arguments (given 3, expected 2)

Procの場合、引数の過不足でエラーが発生しません。
lambdaとは異なり、過不足の部分には[nil]が入ります。

  proc = Proc.new { |arg1, arg2| p "#{arg1}, #{arg2}" }
  proc.call(1)
  #実行結果
  => "1, "

  proc.call(1, 2)
  #実行結果
  => "1, 2"

  proc.call(1, 2, 3)
  #実行結果
  => "1, 2"

・可変長引数と配列展開

[*(アスタリスク)]には種類があります。
それをきちんと区別することがポイントです。
仮引数の前に[*]をつけることで可変長にすることができます。
呼び出す際、以下のように複数の値を入れると配列にしてくれます。

  def foo(*args)
    p args
  end
  
  foo("a", "b", "c")
  #実行結果
  => ["a", "b", "c"]

ややこしかったのがこちらです。
p *args の[*]は配列展開を行うためのものなので以下のようになります。
def foo(*args) の[*]で配列に変換し、p *argsの[*]で配列を展開しています。

  def foo(*args)
    p *args
  end
  
  foo("a", "b", "c")
  #実行結果
  => "a"
  "b"
  "c"

以下のような場合もあります。こちらは
foo(*["a", "b", "c"]) ここの[*]では配列展開されるため、
foo("a", "b", "c")と同様となるので上と同様の結果が得られます。

  def foo(*args)
    p *args
  end
  
  foo(*["a", "b", "c"])
  #実行結果
  => "a"
  "b"
  "c"

まとめると、
仮引数の[*]  ・・・ 可変長引数
メソッド内の[*]・・・ 配列展開
実引数の[*]  ・・・ 配列展開
となります。

他にも
・ inspectとto_sの違い
・ メソッド探索
・ モジュールのincludeやextend,prependの継承チェーン
・ superとsuper()の挙動の違い
・ クラス変数の値
・ Fiberクラス
などRuby歴2年では知らなかったこともたくさんありました。

感想

Silverはメソッドの暗記が主だったような感じがしますが、GoldがRubyの仕組みを理解する必要がありました。
勉強をしていて楽しかったのは圧倒的にGoldです。Rubyを理解する上で良いステップアップの機会になったと思います。 Rubyに興味がある方はまずSilverから挑戦してみてはいかがでしょうか。