ホーム ブログ ページ 36

Kali Linux 2017.1 導入と日本語化

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Kali Linux(2017.1)をVirtualBoxにインストールして日本語化を行ってみました。Kali Linuxは、セキュリティ診断用ツールが標準で用意されている、Linuxディストリビューションです。新バージョン2017.3については、関連の記事を参照ください。

はじめに

Kali Linuxは、セキュリティ診断ツールを含むLinuxディストリビューションです。利用の仕方により不正アクセス行為と判断される可能性ががあります。またサービス停止やデータの破損が起こる場合もありますので事前にバックアップを行うなどしてください。そして必要に応じて管理者の許可を得て利用してください。

今回は、Light版の導入を行います。通常版については、下記の記事などを参照してください。

Kali Linux 2017.3 リリース

Kali Linux 2017.3 がリリースされてます。とても導入が楽になってます。新バージョンについては下記の記事も参照ください。
Kali Linux 2017.3 導入と日本語化

Kali Linuxの特徴などについて

  • Debian派生のLinuxディストリビューションです。
  • デジタルフォレンジック、ペネトレーションテスト(侵入テスト)用などのツールが用意されている。
  • 基本的に、root権限で作業を行う。
  • 現在は、ローリングリリースを採用している。
  • バージョン2017.1がリリースされた。

Kali Linux 公式サイト
https://www.kali.org/

主な収録ツール

今回はLight版を初期導入しますが、通常盤には多数のツールが導入されています。(Light版も容易に追加導入できます。)
Nmap、Aircrack-ng、Wireshark、Metasploit Framework、Armitage、Burp SuiteOWASP ZAP、BeEF、sqlmap、wpscan など

※Burp Suiteの日本語化については、Burp Suiteを日本語化する方法として記事を書いております。
※Owasp ZAPについては、Mac版のOWASP ZAPで脆弱性チェックの設定として記事を書いております。

VirtualBox上にインストールする

仮想化ソフトウェア、VirtualBoxをインストールし、Kali Linuxのイメージを導入、起動させます。

VirtualBoxをインストールする

あらかじめ下記サイトからダウンロードを行いVirtualBoxをインストールしてください。

VirtualBox 公式サイト
https://www.virtualbox.org/

Kali Linux イメージファイルのダウンロード

Kali Linux Downloads – Virtual Images イメージファイルのダウンロード先
https://www.offensive-security.com/kali-linux-vmware-virtualbox-image-download/

書いている時点で、直接ダウンロード出来るのはバージョン2017.1です。
中段のKali Linux VirtualBox Imagesタブをクリックし、環境に適したものをダウンロードします。今回は、Light版を導入してみます。

Kali Linux ダウンロード

Kali Linux 仮想アプライアンスのインポートと設定

VirtualBoxを起動し、ファイル、仮想アプライアンスのインポートで、先ほど展開したKali-Linux-Light-2017.1-vbox-XXXXX.ovaを選択しインポートします。

Kali Linux インポート

トラブルを避けるため、すべてのネットワークカードのMACアドレスを再初期化にチェックを入れます。

Kali Linux VirtualBox MACアドレス設定

デフォルトの設定でも問題はないですが、ネットワークの割り当ては、診断対象環境との通信の関係上、ブリッジ などがよいかと思います。その他は、好みによって設定を変更します。私はメモリを4GBぐらいにしています。

Kali Linux VirtualBox ネットワーク設定
Kali Linux VirtualBox メモリ設定

Kali Linuxの起動と更新

Kali Linuxの起動を行いログインします。Kali Linuxのパスワードは、toorに設定されています。
 ユーザー名:root
 パスワード:toor

Kali Linux ログイン画面

他のパッケージ導入前に、既存のパッケージを最新に更新してしまいましょう。
画面下部の黒っぽいアイコンのターミナルを起動します。
そして下記のコマンドを入力します。しばらく時間がかかり、確認のため途中にyなどの入力が必要となります。

# apt-get update
# apt-get upgrade

Kali Linuxの日本語利用について

英語環境のまま利用している方も多いようですが、ここでは日本語で利用できるように設定します。

1. Kali Linuxの日本語設定

ターミナルからコマンドで設定変更します。
変更画面では、タブキー、スペースキー、エンターキーなどを使います。

ロケールの変更

# dpkg-reconfigure locales

ja_JP.UTF8 を選択します。

Kali Linux ロケール変更1
Kali Linux ロケール変更2

キーボードの変更

日本語キーボードを利用できるようにします。

# dpkg-reconfigure keyboard-configuration

106キーが、ぱっと見で見当たらなかったのでとりあえず105キーで進めます。

Kali Linux キーボード変更1

Otherを選びます。

Kali Linux キーボード変更2

2回ほどJapaneseを選びます。あとはデフォルトでよいかと思います。

Kali Linux キーボード変更3

タイムゾーンの変更

タイムゾーンを環境に合わせて変更します。今回は東京に合わせます。

# dpkg-reconfigure tzdata

Asiaを選びます。

Kali Linux タイムゾーン変更1

Tokyoを選びます。

Kali Linux タイムゾーン変更2

2. Kali Linuxへ日本語関連パッケージの導入

下記コマンドで日本語関連パッケージをまとめて導入してしまいます。

# apt-get install task-japanese task-japanese-desktop

完了したら、一度シャットダウンして起動しなおします。

3. Kali Linuxの日本語変換の設定

Mozcがroot権限で、そのまま動かないため、ここではMozcを無効にします。
Mozcを利用したい場合は、一般権限で動作する別のディストリビューション(BackBoxなど)をお勧めします。Mozc自体の変更でも動作させることはできるようです。

右上のアプリケーション 設定 入力メソッド(青いアイコンの方)を選択します。

Kali Linux 日本語入力メソッド

使用可能にする入力方式を編集します。

Kali Linux 日本語入力方式

Mozcを無効にします。

Kali Linux Mozc無効

通常版のパッケージ追加

Light版は、導入されているツールが少ないです。
下記のコマンドで、通常版と同様のツールをまとめて導入できます。

# apt-get install kali-linux-full

Kali Linux 2017.1 導入完了

Kali Linux 2017.1 Lightを、VirtualBoxにインストールし日本語表示、日本語キーボードの利用、日本語変換が行えるようになりました。

Kali Linux 日本語化

関連記事など

脆弱性診断サービスなど

弊社、アピリッツではセキュリティ診断サービスを行っております。
下記リンクから内容の確認と、問い合わせが可能です。

http://security.appirits.com/

アピリッツの新卒合宿2017

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは。久々に記事を書きます。 今回は、今年の新卒合宿の風景をご紹介したいと思います。

今年は、新卒26名と先輩社員で千葉県にある「リソルの森」に行って参りました。
運良く前日降っていた雨も上がり、清々しい朝を迎え緑いっぱいの目的地へ到着。
enter image description here

早速、研修室に集合してグループワーク開始!緊張する新卒の皆さん。
enter image description here

おじさんたちが見守る中、毎年グループワークを中心に、様々な難題をクリアしていくのですが、今年はアイスブレイクとしてゲーム性のあるグループワークをはじめに行いました。緊張していた面々も一つ目のグループワークを行うことで、コミュニケーションが取れはじめました。
enter image description here

意見をまとめて各グループでの発表。最初の発表は流石に緊張してましたが、徐々にペースを掴み自分たちの言葉でしっかりと自分たちの意見を発表していました。
enter image description here

その後、様々な難題を力を合わせクリアしていき、夜は付き添って頂いた先輩社員とBBQをしながらコミュニケーションを取りました。(轆轤を回す魚谷取締役
enter image description here

掲載できる写真だけアップします。
enter image description here

そして翌日は、また朝から課題をクリア。
運動を行い、大浴場で汗を流して、最後の課題。
とある新卒に全ての笑いを持っていかれるというハプニングもありつつ、疲れと反省でぐったりしながら帰宅の途に就きました。

フレッシュな新卒の皆さんが、社会人としての心得を感じ取り、キリリとした表情に変わっていく、そんな合宿なのでありました。(先輩社員たちは、それはそれで刺激を貰っております)

また来年忘れなければ、合宿の風景をアップしたいと思います。

Rails×Basic認証×Rspecでつまづいた

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

 入社してから3週間目の新入社員、HelloWorld?です。
 現在、先輩から渡された課題をある程度こなした頃です。
 その課題に関しては色々とつまづいた所があって、その一つに対してこのappiritsでこういうサイトがあるよー、という事でアウトプットしてみようかなと(新卒一番乗りしたかったのもあるよ!)。

 で、問題のつまづいた所に関して、の前にどういう課題を渡されたかに関して大まかに。
 ・Railsを使って簡単な擬似管理画面を作る
 ・Rspecでテストコードを入れる
 この他にも様々な要件がありましたが、取り敢えず問題となったのは、この組み合わせで起きた事でした。

 後、自分のスキルも提示しておきます。
 ・プログラム経験:大学で4年間、主にC,C++、それから多少のJava,Javascript
 ・Ruby,Railsに関してはこのAppiritsでインターンの時に2週間教わった+社員となってからの2週間程度
 ・フレームワーク使用経験は上記のみ
 プログラム自体は書き慣れてはいるけど、フレームワークとかは使った事ないよー、という感じです。


 そして、詰まった所に関して。

 管理画面という事で、Basic認証を導入してみて。そして、Basic認証を通してテストコードも書こう、という事をやってみる事にしました。
 実装した所で参考にしたサイト:
 http://threetreeslight.com/post/59357292457/rspecにおけるbasic-auth対応

 Basic認証設定部分。全てのページに対して掛けています。
app/controller/apprication_controller.rb

class ApplicationController < ActionController::Base  

protect_from_forgery with: :exception
before_filter :basic

    private
      def basic
        authenticate_or_request_with_http_basic do |user, pass|
          user == 'user' && pass == 'admin'
      end
end

Controllerのテストをさせる部分&テストをさせる為にBasic認証を通す部分
(DRYの為にSupportに書いてmoduleを作ったり、spec_helperに書き込んだりするべきだけど、取り敢えずここのテストしか書いてないので)
(更に加えるとテストする時はBasic認証とか外してテストするべきだよね、とか書いてあったりしたけど、今回はこういう事をしました、という事で)
spec/controllers/users_controller_spec.rb

RSpec.describe UsersController, type: :controller do

  before(:all) do
    @request.env ||= {}
    user = "user"
    pass = "admin"
    @request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pass)
  end

  describe "GET #index" do
...

結果
 動くけど、Basic認証通ってない!

 それから色々試した所、
 ・requestがそもそもnilだと言われていた。
 ・before(:all)に入れずにテスト単体それぞれでBasic認証を通すようにしたら通った。
  ┗before(:all)はその前のモデルのテストでちょっと使ったりもしたから、これは問題ないんじゃないか……と思って訳が分からなくなる。
 そこまで分かった後、先輩がちゃっと解決してくれました。

 その事が色々書いてあったりするサイト:
 http://qiita.com/srockstyle/items/6397c458d8f12dfcd02c
 http://nilp.hatenablog.com/entry/2014/05/28/003335


結論
 参考にしたサイトは、実装をした際に単一のテストしか記述していなくて。複数のテストに対してBasic認証を通す為には一つ、:allというホックに対して問題がありました。

describe MyClass do
  before(:each) { } # このグループのそれぞれのテストの前に実行される
  before(:all)  { } # このグループの最初のテストの前に1度だけ実行される
end

 before:allで一回だけ認証通しても、それぞれで認証通さないと全部弾かれてしまうよね、という結果でした。


修正
 spec/controllers/users_controller_spec.rbのbefore(:all)をbefore(:each)に変更。
 それだけ。


反省
 まだ合計で1ヶ月程もrubyに対してもrailsに対しても学んでいないから、仕方ない事だけれども、それぞれのメソッドとか、仕様とかに対して上部しか分かっていないなー、と。分かったつもりになっている、という事でここは間違いないだろう、と決めつけてそこをエラー箇所から外していたので、自分では見つけられなかった。
 まだ、そんな前提から疑わなければいけない段階でもあるし、そんな前提からこれからも疑っていたら時間が掛かり過ぎるし、デバッグの時間を削る為に、幅広い事が出来るようになる為にも積極的に知識を身につけていかないとなー、と。

プロジェクト管理するうえで簡単で効果のある小技みっつ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

たまごです。 今日は、プロジェクト管理するうえで簡単で効果のある小技をいくつかご紹介したいと思います。

新規参画者には、まずレビュータスクを振る

新規参画者がプロジェクトに入ってまずやる作業といえは、環境構築とドキュメント読みです。

自分も経験があるのですが、このドキュメント読みはなかなか苦行です。よくわからない状態で延々と文字を読まなければいけないのは、辛いことです。えてして「とにかく読み切ること」に目的がすり替わったり、場合によっては睡眠導入剤と化してしまうこともあるでしょう。

そこで、自分の場合は、新規参画者に早い段階でレビュータスクを振るよう心がけています。

ドキュメント読みはつまらないけれど、人の粗を探すのは楽しいものです。「レビュー」という実作業を振ることで目的も明確になります。最終的に得られる効果は、新規参画者の案件理解という点で同じなのですが、こちらの方がはるかに理解度が高まります。

プロジェクトとしても、新しい目線で仕様の抜け漏れを指摘してもらるので、WinWinです。

うろうろする

朝会はもちろん効果的ですが、15時とか17時とか、午後のどこかのタイミングで人員の島をうろうろするのがオススメです。

島をうろうろすると、意外と困っていたり、外から見れば自明のことで考え込んでいる場合があります。そういう場合、声をかけて数分話すだけで二時間とか半日の時間を買い戻すことができます。

これが積み重なると、大きいです。

進捗報告表を作る

朝会では、大体昨日の実績と今日の目標を喋ると思います。

なので、昨日の実績と今日の目標を記録する進捗報告表をexcelやスプレッドシートで作って、皆に書き込んでもらうとよいです。

今自分が使っているのは、左が日付で上が人員名になっている進捗報告表です(画像参照)。探せばもっとナイスなツールがあるかもしれませんが、今のところこれです。毎日朝会前までにこれを書いてもらい、朝会では書いた内容を報告してもらうようにしています。

メリットは色々あるのですが、ひとつは口頭だと見逃しがちな点に気付けることです。

何もなしに朝会をしていると、どうしてもその一日にフォーカスして聞いてしまいますが、報告内容を蓄積&一覧化していると、一週間の推移としてどうかという視点でチェックできます。

未来日のタスク計画を書いておくこともできます。「三日かかります」というなら、あらかじめ三日先まで目標欄を埋めてもらえばよいですし、マネージャからの指示があれば、それもあらかじめ書いておけばよいです。

よしんば何かの事情で朝会がスキップになった時も、報告表を一覧化しておけば安心です。ざっとチェックすれば、皆の進捗具合がわかるし、翌日にまとめて朝会する際も追うのが楽です。

CloudFrontの「Restrict Bucket Access」と「Restrict Viewer Access」の違いがよくわからなかったので検証してみた

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

CloudFront の設定項目「Restrict Bucket Access」と「Restrict Viewer Access」がそれぞれどのような役割をもっているか理解が曖昧だったので実験で検証してみました。

TL;DR

  • S3バケット上のオブジェクトのACLをprivateにすると一般ユーザはS3のURLでオブジェクトへのアクセスが行えなくなる。
  • Restrict Bucket Access を Yes に設定すると、ユーザ自身の代わりに「オリジンアクセスアイデンティティ」に設定された権限によりS3にアクセスできるようになる。
  • Restrict Viewer Access を Yes にすると、署名付きURL(または署名付きCookie)によるアクセスしか許可しなくなる。
  • Restrict Bucket Access を Yes, Restrict Viewer Access を No の組み合わせで設定したら、署名付きURL/署名なしURLいずれでもアクセス可能となる。さらに署名付きURLの期限が切れていても問題なくアクセスできてしまうので注意‼️

上記については以下の公式ドキュメントに詳しく記載されています。(といっても初見ではイマイチ理解できなかったので結局検証したんですが…😅)

CloudFront を使用してプライベートコンテンツを供給する – Amazon CloudFront

実験内容

実験方法は以下のとおり。

  • S3 バケットのオブジェクトは private (オーナー以外のアクセス権なし)と、public(EveryoneのRead権あり)の 2 種類用意。
  • S3 バケット自身には以下のように CloudFront のオリジンアクセスアイデンティティによる参照アクセスを許可(以下は例のためIDとかバケット名は存在しないものになっている)
{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity xxxxxxxxxxxxx"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::xxxxxx-bucket/*"
        }
    ]
}
  • CloudFront で Restrict Bucket Access, Restrict Viewer Access それぞれの設定の組み合わせによって、S3の public/private それぞれのオブジェクトへのアクセス結果がどのようになるか検証。

実験結果

実験の結果は以下のとおり

実験結果

実験の結果以下のことがわかりました。
(以下では、Restrict Bucket Access を “Bucket”、Restrict Viewer Access を “Viewer” と表現してます)

  • Bucket:YES, Viewer:YES の場合:
    • 現時点で有効な署名付きURLでのみアクセス可能。
    • 署名無しのURLでアクセスするとステータス 403 でXMLのエラーメッセージとして”Missing Key”が返ってくる。
  • Bucket:YES, Viewer:NO の場合:
    • 署名付きURL/署名なしURLいずれでもアクセス可能。
    • しかも、署名付きURLの有効期限が切れてもアクセス可能。
  • Bucket:NO, Viewer:YES の場合:
    • publicなS3コンテンツに署名付きURLでのみアクセス可能。
    • privateなコンテンツに署名付きURLでアクセスすると、ステータス 403 でXMLのエラーメッセージは”Access Denied”が返ってくる。
    • privateなコンテンツに署名なしURLでアクセスすると、ステータス 403 でXMLのエラーメッセージは”Missing Key”が返ってくる。
  • Bucket:NO, Viewer:NO の場合:
    • privateなコンテンツには一切アクセスできない。
    • publicなコンテンツには署名付き/署名なしいずれのURLでもアクセス可能。

この結果で予想外だったのが2番目のケースで、「署名付きURLの有効期限が切れていたとしても関係なく普通にアクセスできる」という点でした。

Restrict View Access で署名付きURLによるアクセス制限をかけていないので、当たり前と言えば当たり前のことなんですが、予想外の結果でびっくりしました。

もし設定をミスっても署名付きURLで普通にアクセスできてしまい、あえて有効期限切れの場合のテストを行わないと設定ミスに気付かずそのまま本番運用…😱 なんてことにならないように注意が必要ですね。

まとめ

CloudFont + S3 でプライベートなコンテンツを配信する場合、S3及びCloudFrontを以下のように設定する必要がある。

  • S3は以下のとおり設定する
    • S3にオブジェクトをアップロードする際のパーミッションは private(オーナーのみアクセス可能)とすること
    • S3バケットはバケットポリシーでオリジンアクセスアイデンティティによるアクセスを許可すること
  • CloudFront ディストリビューションは以下のとおり設定する
    • Restrict Bucket Access を Yes に設定し、S3のバケットポリシーで許可されているオリジンアクセスアイデンティティでS3にアクセスするように設定すること
    • Restrict Viewer Access を Yes に設定し、署名付きURLによるアクセスを必須とすること

設定内容を正しく理解して安全にシステムを運用したいですね。

S3から複数のファイルを取得しつつ on-the-fly でZipを作ってブラウザに返す

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

S3にダウンロードさせたいファイルが複数あるが、zipファイルでまとめて1度にダウンロードさせたいが、そんなAPIはそもそも無いので zipline という gem を使ってみました。

課題

S3にダウンロードさせたいファイルが複数あるが、zipファイルでまとめて1度にダウンロードさせたい

解決策

  • EC2インスタンスで稼働しているWebアプリケーション側でS3上の複数のファイルをまとめてzipを作成
  • zipファイルを作成するそばからクライアントへレスポンスを返す(chancked response)
    • ちょうどそんなことをやってくれる zipline という便利な gem が存在する

(タイトル画像のようなイメージ)

テスト用アプリを作る

試しに Rails アプリケーションを作ってみる

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.10.5
BuildVersion:   14F2109

$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin14]

$ rails --version
Rails 5.0.1

Railsアプリの準備

まず、準備として rails コマンドでアプリの雛形を用意

$ rails new zipline_test

上記が完了したら作成されたディレクトリに移動

$ cd zipline_test

Gemfileを編集して ‘zipline’ と ‘aws-sdk’ を追加してそれらのgemをインストール

$ echo "gem 'zipline'" >> Gemfile
$ echo "gem 'aws-sdk'" >> Gemfile
$ bundle install --path ./bundle

これでほぼ準備OK
アプリケーションを書いていく

ルートとコントローラを作る

まずURIを定義するため、config/routes.rb を以下のように編集。

Rails.application.routes.draw do
  get "download/zip"
end

次に、上記で定義したURIに対応するコントローラを定義する。
以下のコマンドでコントローラの雛形を作成。

$ rails g controller download

すると、app/controllers/download_controller.rb が作成されるので、そのファイルを以下のように編集。

class DownloadController < ApplicationController
  include ActionController::Streaming
  include Zipline

  AWS_S3_REGION = "ap-northeast-1"
  AWS_S3_BUCKET = "zipline-test"

  def zip
    zipline(s3files, "s3files.zip")
  end

  private

  # ダウンロード対象のファイルを順次zipに固めながら chunked response としてクライアントに返す
  def s3files
    s3 = Aws::S3::Client.new(region: AWS_S3_REGION)
    # ダウンロード対象のファイル
    files = %w(
      file1.json
      file2.json
      file3.json
    )
    files.lazy.map do |file|
      logger.debug "get file from s3 : #{file}"
      s3_object = s3.get_object(bucket: AWS_S3_BUCKET, key: file)
      

[s3_object.body, file]

end end end

  • AWS_S3_REGION は自分のS3バケットを作成したリージョンに
  • AWS_S3_BUCKET は自分のS3バケットの名前に
  • file1.json, file2.json, file3.json はS3バケット上のダウンロードさせたいファイル名に

サーバを起動する

あらかじめAWSに接続するためのcredential関係の環境変数(AWS_SECRET_ACCESS_KEY,AWS_ACCESS_KEY_ID)を設定してからサーバを起動する

$ export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxx
$ export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxx
$ rails s

これで http://localhost:3000/で サーバが立ち上がるはず。

URIアクセスしてみる

ブラウザで http://localhost:3000/download/zip にアクセスするとダウンロードが始まり、zipファイルがダウンロードされるはず。

参考

Rubyのサポート期間一覧

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

脆弱性診断などで、各種ソフトウェアのバージョンやサポート期限について調べることが多い為、プログラミング言語 Rubyの公式サポート期間、サポート終了期限(eol)の状況について、簡単に一覧にまとめました。また、確認できる公式のリンクを記載しています。

公式サポート期間

Ruby eol サポート期間

バージョン
メンテナンス状態
最新リリース
最新リリース日
セキュリティサポート終了

2.7系
通常
2.7.1
2020年3月31日


2.6系
通常
2.6.6
2020年3月31日


2.5系
通常
2.5.8
2020年3月31日


2.4系
メンテナンス終了
2.4.10
2020年3月31日
2020年3月31日(予定)

2.3系
メンテナンス終了
2.3.8
2018年10月17日
2019年03月31日

2.2系
メンテナンス終了
2.2.10
2017年3月28日
2018年3月31日

2.1系
メンテナンス終了
2.1.10
2016年4月1日
2017年3月31日

2.0系
メンテナンス終了
2.0.0-p648
2015年12月16日
2016年2月24日

1.9系
メンテナンス終了
1.9.3-p551
2014年11月13日
2015年2月23日

1.8系
メンテナンス終了
1.8.7-p374
2013年6月27日
2014年7月31日

※2020年4月現在
正確な情報は、公式サイトなどをご確認ください。

参考サイト

Ruby Releases
https://www.ruby-lang.org/en/downloads/releases/

Ruby Maintenance Branches
https://www.ruby-lang.org/en/downloads/branches/

JVN iPedia 脆弱性対策情報データベース(Ruby)

その他

ソフトウェアライフサイクル考慮した保守契約を行いまいましょう。
リスク受容を選択しなければならない場合、リスクを把握したうえで、ステークホルダーと合意、責任の所在を明確にし書面などに記録しておきましょう。

※詳しくは、別途調べてください。

脆弱性診断サービスなど

弊社、アピリッツではセキュリティ診断サービスを行っております。

下記リンクから内容の確認と、問い合わせが可能です。

http://security.appirits.com/

Windows でも Mac でもツールを使用せずに元に戻せるファイル分割

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

サイズの大きなファイルを分割して共有したい。 けれど、共有する相手にWindowsユーザとMacユーザがいる。 という様な場合、WindowsでもMacでも使用できるファイル分割・結合ツールを使用する方法もあるが、 以下の方法でファイル分割すれば、専用ツールなしで(WindowsやMacの標準で)結合できるようになる。

分割方法 (Mac)

split origin.txt -b 100m -d splitted.txt_

origin.txtの部分は分割したい対象のファイル。
100mの部分は、分割したいファイルの単位。この例では100MBごとのファイルに分割される。
splitted.txt_の部分は、分割後のファイル名。この例では「splitted.txt_00」、「splitted.txt_01」、…という様なファイルが生成される。

結合方法(Windows)

copy /b splitted.txt_* origin.txt

結合方法(Mac)

cat splitted.txt_* > origin.txt

注意

残念ながら分割の方はMacで行うしかない。ただし、Windowsでもbashが使えるツールがあれば、使用できる。

3分リファクタリング SelectableAttr 編

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

社内でRails標準のEnumよりも多く使われているSelectableAttrについて。

EXAMPLE

カードのレアリティを 0 〜 5 の整数値で表現します

class Card < ActiveRecord::Base
  include ::SelectableAttr::Base

  selectable_attr :rarity do
     entry 0, :N, 'ノーマル'
     entry 1, :HN, 'ハイノーマル'
     entry 2, :R, 'レア'
     entry 3, :HR, 'ハイレア'
     entry 4, :SR, 'スーパーレア'
     entry 5, :LG, 'レジェンド'
  end
end

BEFORE

レアリティの定数を参照するために、 xxx_id_by_key というクラスメソッドを使っています。

if @card.rarity == Card.rarity_id_by_key(:SR)
  puts "スーパーレアが限界突破!"
  @card.rarity = Card.rarity_id_by_key(:LG)
  @card.save!
end

AFTER

インスタンスメソッドに定義された xxx_key を使えば、値をシンボルで取り出すことができます。

if @card.rarity_key == :SR
  puts "スーパーレアが限界突破!"
  @card.rarity_key = :LG
  @card.save!
end

POINT

rarityというアトリビュートが定義されていると、以下の3つのアクセサが定義されます。

  • #rarity_key rarityの値に応じたシンボルを返す
  • #rarity_key= シンボルを受けて値に変換してrarityに代入する
  • #ratity_name rarityの値に応じた名称を返す

また、クラスメソッドのcreateや、インスタンスメソッドのupdateなどハッシュを引数にとるメソッドもrarity_keyという名前でシンボルを受け付けるようになります。

card = Card.create(rarity_key: :LG)
card.update(rarity_key: :SR)

REFERENCE

https://github.com/akm/selectable_attr

VERSIONS

Ruby MRI 2.1.1
Rails gem 'rails', '4.1.4'
selectable_attr (0.3.17)
selectable_attr_rails (0.3.15)

AWSでバウンスメール対策【AWS総連携】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、2017年初投稿の棚旬です。今回は、メール配信を行っているサービスで重要となってくるバウンスメール(何らかの原因で配信エラーになったメール)対策について記載しようと思います。バウンスメール対策は、AWSが提供しているサービスを使用すると簡単にバウンスメールの処理が可能です。この記事ではAWS周りの設定について記載しています。AWSが提供しているAPIを利用してバウンスとなったメールを取得する方法については別の記事で記載しようと思います。

AWSの各サービスについて

バウンスメール対策を行うにあたり、今回は3つのAWSサービスを使用していきます。各サービスについてはリンク先の説明で確認しましょう。
SES

Amazon SES は、ユーザー自身の E メールアドレスとドメインを使用して E メールを送受信するための、簡単で費用効率の高い方法を提供する E メールプラットフォームです。

Simple Email Service-Amazon Web Services

SNS

Amazon Simple Notification Service (Amazon SNS) は、高速かつ柔軟な完全マネージド型のプッシュ通知サービスです。このサービスを使用すると、個々のメッセージを送信したり、多数の受信者にメッセージをファンアウトしたりできます。Amazon SNS により、簡単かつコスト効率の高い方法で、モバイルデバイスユーザーおよびメール受信者にプッシュ通知を送信したり、他の分散サービスにメッセージを送信したりできます。

Simple Notification Service-Amazon Web Services

SQS

Amazon Simple Queue Service(SQS)は、高速で、信頼性が高く、スケーラビリティに優れ、十分に管理されたメッセージキューサービスです。

Simple Queue Service-Amazon Web Services

はい、では早速設定していきましょう。

SNSの作成

  1. AWSコンソールからSNSを選択(リージョンはバージニア北部)
  2. Create Topicを選択 enter image description here 3.【Topic name】【Display name】を入力 【Display name】は10文字以内の制限があるのと、バウンスを受信した時の宛名になるので分かりやすく判別しやすい名前にしましょう。 enter image description here

SESにアドレスの登録

  1. AWSコンソールからSESを選択(リージョンはバージニア北部)
  2. SES Home からEmail Addressesを選択し、Verify a New Email Addressを選択
  3. Email Address を入力する
  4. 認証メールが届くので確認。SESのアドレス一覧で認証されたアドレスのStatusがverifiedに変わる enter image description here

SNSのサブスクリプション登録

  1. SNSのメニューからTopicsを選択し、topic名を選択
  2. create subscription を選択
  3. 【Protocol】Email【Endpoint】SESに登録したアドレスを入力 【Topic ARN】は作成したSNSの詳細に明記されている値を使用 enter image description here
  4. 認証メールが届くので確認
    enter image description here
    click here to unsubscribeをクリックするとサブスクリプションが解除されてしまうので注意。(コンソールからでも削除可能)SESとSNSの連携
  5. アドレスの詳細からNotificationsのEdit Configurationを選択
    enter image description here
  6. SNS Topic Configuration
    【Bounces】【Complaints】は作成したSNSを選択
    ※BouncesとComplaintsの両方を選択しないと、Email Feedback Forwarding が選択不可となり、通知設定の解除がAPI経由で変更できない
    Email Feedback ForwardingはDisabledを選択

SQSの作成

  1. AWSコンソールからSQSを選択(リージョンは東京)
  2. 新しいキューの作成を選択 enter image description here
  3. 【キュー名】を入力する。キューの属性はデフォルトで良い。
  4. SNSからの受信設定 アクセス許可タブの【アクセス許可の追加】を選択
  5. 作成したキューへのアクセス許可 enter image description here 【効果】許可 【プリンシパル】全員 【アクション】SendMessage 【限定条件】None 【条件】ArnEquals 【キー】aws:SourceArn 【値】作成したSNSのARN値

SNSとSQSの連携(SNSにサブスクリプションの登録)

  1. AWSコンソールからSNSを選択(リージョンはバージニア北部)
  2. 作成したSNSトピック詳細からCreate subscriotionを選択
  3. 【Protocol】Amazon SQS 【Endpoint】作成したSQSのARN値

IAMユーザの作成

  1. AWSコンソールからIAMを選択
  2. メニューのユーザーから【ユーザーを追加】を選択
  3. 【ユーザー名】、【アクセスの種類】はプログラムによるアクセスを選択
  4. 【既存のポリシーを直接アタッチ】を選択(2回目からはアクセス権限を既存ユーザーからコピーで可能)
  5. SQSで検索し、AmazonSQSFullAccessを選択 同様にSESで検索し、AmazonSESFullAccessを選択
  6. .csvのダウンロードを選択 アクセスキーとシークレットアクセスキーを控える

設定確認

設定が終了したのでテストメールを送ってみましょう。
1. SESに登録したメールアドレスを選択し、Send a Test Emailを選択
2. Toにバウンス扱いになるメールアドレス(bounce@simulator.amazonses.com)を入力。Subject、Bodyは任意。
3. Send Test Mailを選択
4. 作成したSQSを選択し詳細をチェック
enter image description here
利用可能なメッセージ(可視)が1になっていたら正しく設定ができています。また、SESに登録したアドレスはSNSにサブスクリプション登録しているので、以下のようなメールも届いているはずです。
enter image description here

バリデーションでコンテキストを活用する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Railsのバリデーションではコンテキストと呼ばれる情報を使うことができます。
コンテキストはシンボルで表現されます。

コンテキストの種類

レコードをINSERTするときのコンテキストは :create、 UPDATEするときのコンテキストは :update です。

レコードを最初に保存するときと、あとで更新するときで検査する項目や内容を変えたいとき、 :create と :update で区別すればうまく実装できます。

またvalid?などで特に指定しない場合のデフォルトのコンテキストは nil です。

コンテキストを定義する

その他にも、ユーザーが任意のシンボルを使ってコンテキストを指定することができます。

たとえばここで、 :change_password というシンボルを使ってユーザーのパスワード更新というコンテキストを表そうと思います。

saveするときのコンテキストを指定する

user.save(context: :change_password)

バリデーションを実行するときにコンテキストを指定する

user.valid?(:change_password)

コンテキストを活用する

このコンテキストをバリデーション側で受け取るには on: パラメータを使います

validates :password, presense: true, on: :change_password

こうしておくと、savevalid?:change_passwordというコンテキストが指定されたときだけ、このバリデーションがチェックされます。

逆に「このコンテキストでないときだけチェックしたい」という指定をするときは、カスタムバリデーションのメソッドを書いて、その中でコンテキストをチェックすることができます。

validate :check_not_on_password

def check_not_on_password
  # コンテキストが :change_password のときはなにもしない
  return if validation_context == :change_password

  :
  :
end

【Rails】RailsのJavaScriptをクラス分け【JavaScript】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

RailsでJavaScriptを読み込んでいるかと思いますがクラス分けをしていないではないでしょうか。 そんな時の参考になればと思います。

なぜクラス分けした方がいいのか。

アセッツパイプラインでjsやcssを結合して高速化してくれますがjsを一括で読み込んでしまうため、アクションによってjsの機能を切り替える必要があるためです。

機能を切り替えないとどんなことが起こるのか。

products.coffee

$ ->
  $('.name').css('font-size', '10px')

categories.coffee

$ ->
  $('.name').css('font-size', '20px')

この場合には読み込まれた順番によって.nameのフォントサイズが変わってしまいます。

クラス分けの手順

各コントローラ各アクション毎にクラスをnewするようにします。

1. app/views/layouts/application.slim

= javascript_include_tag 'application', 'data-turbolinks-track' => true
      .
      .
      .
body data-controller="#{controller.controller_name}" data-action="#{controller.action_name}"

2. app/assets/javascripts/application.coffee

#= require_tree .

3. app/assets/javascripts/js_loader.coffee

$ ->
  new JsLoader

class JsLoader
  constructor: ->
    @initialize_script_classes()

  initialize_script_classes: ->
    controller_name = $('body').data('controller')
    action_name = $('body').data('action')
    page_name = "#{contoller_name}:#{action_name}"

    switch page_name
      when 'products:index', 'products:show'
        new Product
      when 'categories:new', 'categories:create',  'categories:edit',  'categories:update'
        new Category
      .
      .
      .

4. app/assets/javascripts/products.coffee

class @Product
  constructor: ->
    @initialize_select_box()

  initialize_select_box: ->
    $('select').click ->
      .
      .
      .

これでクラス分け完了。

ついでにCSSも分ける

各コントローラ各アクション毎にstyleを切り替えられるようにします。

1. app/views/layouts/application.slim

= javascript_include_tag 'application', 'data-turbolinks-track' => true
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
      .
      .
      .
body id="#{controller.controller_name}-#{controller.action_name}" data-controller="#{controller.controller_name}" data-action="#{controller.action_name}"

2. app/assets/stylesheets/application.scss

@import 'products';
@import 'categories';
.
.
.

3. app/assets/stylesheets/products.scss

#products-index {
  p {
    color: red;
  }
}

#products-show {
  p {
    color: blue;
  }
}

Dockerを試してみる(4)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Dockerを試してみる(3)の続きです。今回はDockerfileを試してみます。 前回はdocker-composeについて試したので、順番逆なんじゃね?って感じがしますが置きになさらず

Image と Container

Dockerfileを使う前にあらためて ImageとContainerについておさらいします。

DockerはOS上で軽量の仮想環境(コンテナ(Container)と呼ばれる)を実行するためのエンジンとエンジンを操作するツールを提供したものです。たとえば docker run コマンドでは、次のコマンドでDBコンテナを起動させることができます。

$ docker run -d -e "MYSQL_ROOT_PASSWORD=password" --name mysql mysql:5.6

起動したコンテナは次のコマンドで確認できます。

$ docker ps 
  CONTAINER ID IMAGE     COMMAND                 CREATED         STATUS         PORTS    NAMES
  f78a4be66ee8 mysql:5.6 "docker-entrypoint.sh"  15 seconds ago Up 14 seconds   3306/tcp  mysql

この出力にIMAGEという列があります。これはコンテナの大本となる、ファイルや起動コマンドを定義したイメージと呼ばれるものです。上の出力だと mysql:5.6というイメージを使用しています。docker runコマンドの引数でも指定していますね。

このイメージは、Docker Hubというレポジトリにあるものを利用しています。mysqlやmemcachedなどのDocker Hubにあるイメージを使う(pullする)だけで十分かと思います。

しかししばらくすると自分のアプリケーションもコンテナにしたい、ということがあると思います。
その場合、Dockerfileを使ってオリジナルのイメージを作成することができます。

Dockerfile

Dockerのイメージを作成する際に必要なルールを定義したファイルです。
ソースファイルをコンパイルするときに使うMakefileに似たようなものです。

例と実行方法

Dockerfileの例は以下のとおり。

FROM ruby23

RUN yum -y  install mysql-community-devel

COPY docker-entrypoint.sh /
RUN chmod 755 /docker-entrypoint.sh

ENV RAILS_ENV production
ENV PATH /usr/local/ruby-2.3.3/bin:/usr/local/bin:/bin:/usr/bin
ENV RAILS_SERVE_STATIC_FILES false

VOLUME /usr/src/app
WORKDIR /usr/src/app

ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 8080
CMD ["bundle", "exec", "unicorn", "-E", "production"]

このファイルをdocker buildコマンドを使ってビルドします。

$ cd /some/directory
$ vi Dockerfile
$ docker build -t myapp .

文法

Goというプログラミング言語をベースにしています。
コマンド名 引数 が1コマンドで行の先頭から実行されます。

コマンド

コマンド名内容
FROM基本となるイメージを作成する
RUNイメージ内でシェルコマンドを実行する。yumなどでアプリケーションをインストールする場合などに使う。
COPYローカルのファイルを、イメージ内にコピーする
ADDローカルのファイルやディレクトリを、イメージ内に追加する
ENV環境変数を定義する
EXPOSE公開するポートを明示する
VOLUMEマウントポイントを指定する
ENTRYPOINTコンテナ起動時に実行するコマンド(CMDの前に実行される)
CMD引数なしでコンテナを起動したときに実行されるコマンド

【Rails】liquid-railsを使ってみました。【Liquid】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


テンプレートの編集機能をに安全に作れるLiquid。 Rails用に使いやすくなったliquid-railsを使ってみたので紹介します。

そもそもLiquidとは何かという事はここでは紹介しませんのでお気をつけください。

使い方

1.Gemfileに追記してbundle install

Gemfile

gem 'liquid'
gem 'liquid-rails'

一応これだけで拡張子が「.liquid」のテンプレートをLiquidとして読んでくれます。

2.Liquid内で使用するモデルのメソッドを設定する

この設定をしないとLiquid内でモデルのメソッドが呼び出せません。
app/models/product.rb

has_many :categories
liquid_methods :name, :price, :categories

3. Liquid内で使いたい変数を設定する

「liquid_assigns」を使用します。下記の設定でコントローラに記述した「@product」等がLiquid内では「product」として呼び出せます。
app/helpers/application_helper.rb

def liquid_assigns
    view_context.assigns.merge(
      params: params,
      hoge: hoge,
      .
      .
      .

    ).stringify_keys
end

4. 「.liquid」の中身の例

構文の詳細は公式を参照してください。

{% for product in products %}
    {% if true %}
      <p>{{ product.name }}</p>
    {% endif %}
{% endfor %}

<p>商品名1</p>
<p>商品名2</p>
<p>商品名3</p>

Filterの使用

Liquid内で変数の加工やタグを作りたい場合があると思います。その場合はフィルターを記述し、読み込みます。liquid-railsでは最初から「javascript_include_tag」等が記述されています。

app/controllers/concerns/liquid_filter_desuyo.rb

module LiquidFilterDesuyo
  def controller
    @context.registers[:controller]
  end

  def view
    @context.registers[:view]
  end

  def page_title(*args)
   I18n.t(controller.controller_name, *args)
  rescue
    nil
  end

  def html_escape(string)
    ERB::Util.html_escape(string)
  end
end

application_controller.rb

before_action :set_liquid_filter
def set_liquid_filter
  Liquid::Template.register_filter LiquidFilterDesuyo
end

Filterの使い方

構文
※引数が無いフィルターは呼び出せません。(たぶん)

{{ 第一引数 | フィルター名:第二引数, 第三引数,....}}

例:

<p>{{ product.name | html_escape }}</p>
<p>{{ product.name | html_escape | simple_format }}</p>

メソッドを繋げることもできます。詳しくは公式へ

実際にエンドユーザにテンプレートを作成してもらう場合にどうするのか?

1.画面からLiquidテキストを入力してもらいviewと同じディレクトリ構造に保存。

RAILS_ROOT/liquid_templates/products/show.liquid

{% for product in products %}
    {% if true %}
      <p>{{ product.name }}</p>
    {% endif %}
{% endfor %}

2.prepend_view_pathを使用し作ったファイルをテンプレートとして呼び出す。

application_controller.rb

before_action :set_view_path
before_action :set_liquid_filter

def set_view_path
  prepend_view_path Rails.root + 'liquid_templates'
end

def set_liquid_filter
  Liquid::Template.register_filter LiquidFilterDesuyo
end

closure-compilerを使用して javascript ファイルを圧縮したときのメモ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

javascript ファイルを納品する場合に パフォーマンスの改善やセキュリティーの向上の為に圧縮を行う必要があった。今回は closure-compiler を使用させて頂いた。 配布する環境によってスクリプト内で利用するASPサーバやアカウントを分けたかったので環境ごとに圧縮ファイルを出力するようにしてみた。

参考:javascriptを圧縮するwebサービス
http://logic.moo.jp/data/archives/513.html

参考:closure-compiler について
https://developers.google.com/closure/compiler/

インストール(bash)

gem install closure-compiler

コア部分の使い方(ruby)

js_src_string = File.read(original_js_file_path_string)
minified_js_string = Closure::Compiler.new.compile(js_src_string)
File.write minified_js_file_path_string, minified_js_string
# js_src に javascript コードを入れると minified_js に圧縮されたコードが代入される。

こういうのをしました。

require 'rubygems'
require 'closure-compiler'

def gen_minified_js(src, config, out_file)
  # jsソースに xxxx_..._token という文字列を記載しておいて置換する。
  config.each do |k, v|
    key = "xxxx_#{k}_token"
    src.gsub!(key, v)
  end
  File.write out_file, src
end

# 環境ごとの置換文字列
envs = {
  staging: {
    protocol: 'https:',
    host: 'staging.example.com',
    service_key: 'staging'
  },
  localdev: {
    protocol: 'http:',
    host: 'my_development_host', # ローカル開発環境用 hostsファイルに開発サーバのIPで登録してください。
    service_key: 'my_development_key' # xxxテーブルのservice_key を変更してください。
  },
  local: {
    protocol: 'http:',
    host: '192.168.xxxx.xxx',
    service_key: 'our_localtest_key' # 開発メンバー共有テスト環境
  },
  appirits: {
    protocol: 'https:',
    host: 'product.example.com',
    service_key: 'product_development_key' # 本番環境 自社アカウント
  }
}

production_env = {
  protocol: 'https:',
  host: 'product.example.com',
  service_key: 'product_product_key' # 本番環境 納品アカウント
}

# 圧縮対象のjsファイル
src = './workspace/deliverables.src.js'
js_src = Closure::Compiler.new.compile(File.open(src, 'r'))

# 本番用でないファイルはまとめて作る 
js_name_base = './workspace/dir_name_token/js/deliverables.test.min.js'


envs.each do |dir, config|
  gen_minified_js(js_src.dup, config, js_name_base.gsub('dir_name_token', dir.to_s))
end

# 本番用はファイル名が違うようにしたので別途実行
gen_minified_js(js_src.dup, production_env, './workspace/products/js/deliverables.min.js')

※ 上記をファイルに保存し ruby に召し上がって頂く。

Rubyのオブジェクトコピーで気をつけること

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Rubyでオブジェクトを複製する際、知らないとハマってしまいそうなポイントをメモ。

その1:=で代入されるのはオブジェクトの参照

=で代入後、破壊的メソッドを使う場合は注意が必要です。

list1 = ['a', 'b', 'c']``
list2 = list1

list1[0] = 'aa'

list1
=> ["aa", "b", "c"]
list2
=> ["aa", "b", "c"]

list1の変更がlist2にも反映されてしまいました。
初学時に混乱しがちなパターンですが、

list2 = list1

は、list2にlist1の参照を代入する、の意なので、
どちらも同じオブジェクトを参照することになります。

object_idを確認すると、同じオブジェクトを参照していることが分かります。

list1.object_id
=> 70343473882920
list2.object_id
=> 70343473882920

破壊的にオブジェクトの内容が変更された場合、
そのオブジェクト見ている他の変数にも変更内容が反映されます。
 
 

その2:dup、cloneは浅いコピー

これを回避するためにはdup、cloneを使います。
が、いくつか注意点があります。

まずはdup、cloneとも別のオブジェクトとして複製されることを確認。

list3 = [{key:'xx'},{key:'yy'},{key:'zz'}]
list4 = list3.dup
list5 = list3.clone

list3.object_id
=> 70343473688700
list4.object_id
=> 70343473670940
list5.object_id
=> 70343473655820

参照しているオブジェクトが違うので、
list3の変更はlist4, list5に影響しません。

list3.reverse!
=> [{:key=>"zz"}, {:key=>"yy"}, {:key=>"xx"}]
list4
=> [{:key=>"xx"}, {:key=>"yy"}, {:key=>"zz"}]
list5
=> [{:key=>"xx"}, {:key=>"yy"}, {:key=>"zz"}]

しかしこうするとどうでしょう。

list3[0][:key]='ZZ'

list3
=> [{:key=>"ZZ"}, {:key=>"yy"}, {:key=>"xx"}]
list4
=> [{:key=>"xx"}, {:key=>"yy"}, {:key=>"ZZ"}]
list5
=> [{:key=>"xx"}, {:key=>"yy"}, {:key=>"ZZ"}]

それぞれ別オブジェクトなのにlist3の変更がlist4, list5にも反映されてしまいました。
 

dup, cloneは、複製するオブジェクト自体は別物になりますが、
それに含まれる参照先はそのままコピーされるため、
その1と同じ事象が発生してしまいます。(参照先のobject_idが同じ)

list3[0].object_id
=> 70343473688720
list4[2].object_id
=> 70343473688720
list5[2].object_id
=> 70343473688720

これは「浅いコピー」といいます。

dupとcloneはほぼ同じですが、以下の点が異なります。

複製するもの


dup
:汚染状態、信頼状態


clone
:汚染状態、信頼状態、凍結状態、特異メソッド


複製できないオブジェクト


true、false、nil、シンボル、数値

■リファレンス
https://docs.ruby-lang.org/ja/latest/class/Object.html#I_CLONE
 
 

その3:Marshalで深いコピー

Marshalを使うとこの問題が解決します。
Marshalはオブジェクトをシリアライズ/デシリアライズするモジュールで、
いったん文字列(ファイル)として保存したものを読み戻すため、
まったく別のオブジェクトとして複製することができます。

Marshal.load(Marshal.dump(obj))


list6 = Marshal.load(Marshal.dump(list3))
list3[1][:key]='YY'

list3
=> [{:key=>"ZZ"}, {:key=>"YY"}, {:key=>"xx"}]
list6
=> [{:key=>"ZZ"}, {:key=>"yy"}, {:key=>"xx"}]

■リファレンス
https://docs.ruby-lang.org/ja/latest/class/Marshal.html

破壊的メソッドを使う際には、
うっかり複製元/先に変更が影響してしまわないよう
注意が必要です。

【Ruby】変数やクラス定義などのスコープ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

制御構文ではスコープを作らない(if, while、forなど)

Rubyではifやwhile、forなどの制御構文ではスコープを作りません。

if true
  hoge = 'abcd'
end
p hoge #=> abcd

for i in 0..5 do
  i += 1
end
p i #=> 6

# if, for内で定義された変数は抜けた後も有効

ブロックはスコープを作る(each, map, timesなど)

each, map, timesなどブロックを引数にとるメソッドでは
ブロック内でスコープが作られます。

[0,1,2].each do |i|
  total ||= 0
  total += i
end
p total
NameError: undefined local variable or method `total' for main:Object
        from (irb):2
        from /home/hoge/.rbenv/versions/2.1.8/bin/irb:11:in `<main>'

ブロック内で定義された変数totalには
外部からアクセスできません。

ブロック外で定義した変数はブロック内でも有効です。

total=10
[0,1,2].each do |i|
  total ||= 0
  total += i
end
p total  #=> 13

 
制御構文もdo~endがあってブロックのように見えますが、
ブロックではないそうです(要調査)
 

module, class, defもスコープを作る

module, class, defもスコープを作りますが、少し違います。
この場合は外部<=>内部のアクセスはどちらもできません。

num=10
def fuga
  num ||= 99
end
p num   #=> 10
p fuga  #=> 99

フラットスコープ

同じクラス/メソッド定義でも、class,defを使うとスコープが作られて、
Class.newやdefine_methodを使うと作られない、などもあります。

▼classで定義した場合は外側で定義したxにアクセスできない

x = 'XX'
class Hoge
  def method_x
    x
  end
end
Hoge.new.method_x
NameError: undefined local variable or method `x' for #<Hoge:0x007fe556dbc200>
        from (irb):4:in `method_x'
        from (irb):7
        from /home/hoge/.rbenv/versions/2.1.8/bin/irb:11:in `<main>'

▼Class.newやdefine_methodを使うと外側の変数にアクセスできる

x = 'XX'
y = 'YY'
Hoge = Class.new() do
  p y  #=> 'YY'
  define_method(:method_x) do
    x
  end
end
Hoge.new.method_x  #=> 'XX'

これをフラットスコープといいます。

 
 
 
「メタプログラミングRuby」に詳しく記載があるので
とてもおすすめです。
スコープについての記載がとても興味深かったので、
もう少し読み解いて理解を深めたいと思います。

【SVN】コミットをミスった、とすぐに気づいた時の戻し方と正しいコミットをするまでです【CUI】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

svnではコミットをなかったことにすることはできません。 コミットする前のリポジトリをローカル持ってきて再度コミットします。 そうすれば履歴は残りますが、リポジトリの最新の状態はミスる前に戻ります。

svnではコミットをなかったことにすることはできません。
なのでコミットする前のリポジトリをローカルに持ってきて再度コミットします。
そうすれば履歴は残りますがリポジトリはミスる前に戻ります。

ローカルのソースはミスった時のリビジョン番号から持ってきます。
それをまたコミットすればいいですね(ミスり方にもよりますが)。

では手順です。

1. リポジトリを最新にします。

svn up

のちにローカルをマージするときのために最新にします。

2. リビジョン番号を確認します。
リポジトリが正しかった時のリビジョン番号を調べます。

svn log

ここではリビジョン番号が100だったとします。

3. 正しかったときのリビジョンにローカルを戻します。

svn merge -r HEAD:100 .

ローカルのファイルが変更されます。
-r HEAD:100でリビジョンを指定しています。HEADはリポジトリで最新のリビジョンを表します。
.はマージ元です。
ローカルのソースが過去のリビジョンに戻りました。

4. 再度コミットします。

svn commit -m “コミットをミスったので過去の状態を再度コミットします。”

これでリポジトリは元に戻りました。
最新のリビジョンが正常だとちょっとほっとしますね。

5. 最後にミスったときのリビジョンからローカルのソースを戻します。

svn merge -r HEAD:ミスったときのリビジョン番号 .

これで、リポジトリとローカルが元に戻りました。

CentOSでのデフォルトゲートウェイの設定方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

CentOSでのデフォルトゲートウェイの設定方法について手順をまとめます.

0. 環境について

バージョン: CentOS 6.5

1. ルーティングテーブルの確認

routeコマンドを実行して,
Destination項目がdefaultの, Gateway項目で現状のデフォルトゲートウェイを確認する.

[VM:~] $ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.2.0        *               255.255.255.0   U     0      0        0 eth0
192.168.56.0    *               255.255.255.0   U     0      0        0 eth1
default         10.0.2.2        0.0.0.0         UG    0      0        0 eth0

2. 設定の変更

設定ファイルを編集する

[VM:~] $ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0
※ ifcfg-eth0 の部分は対象のNICのものを指定

以下のGATEWAY項目を追加もしくは修正
----
GATEWAY=XXX.XXX.XXX.XXX
----

3. 設定の適用

以下のコマンドで, ネットワークを再起動して設定を適用させる.
このとき, 特に注意することとして, 一時的にネットワークが切断されるため,
フェイルオーバのための監視等を行っている場合,
異常と検知されて, フェイルオーバが発生してしまう可能性がある.
そのため, 事前にフェイルオーバが起こらないようにしておくこと.

[VM:~] $ sudo /etc/rc.d/init.d/network restart

変更後に適用されていることを確認(defaultのGatewayの値が, 設定ファイル内で設定した項目になっていること)

[VM:~] $ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.2.0        *               255.255.255.0   U     0      0        0 eth0
192.168.56.0    *               255.255.255.0   U     0      0        0 eth1
default         XXX.XXX.XXX.XXX 0.0.0.0         UG    0      0        0 eth0

4. デフォルトゲートウェイを経由して、外部に接続する際のグローバルIPの確認方法

以下のコマンドにより, 接続するグローバルIPを返却してくれるサービスを利用する.

[VM:~] $ curl http://httpbin.org/ip
{
  "origin": "xxx.xxx.xxx.xxx"
}

Thinreportsを使った感触

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Railsのwebアプリケーション上で、PDFを自動作成させたい、ということがあり、 その際に「ThinReports」というツールを使う機会があったので、 このツールの良い所や、使い辛いと思った所をまとめてみました。

利点

1. 専用のエディタが使える

googlechromeにて、専用のエディタアプリが用意されており、
これを使うことでかなり視覚的にPDFのレイアウトを組むことが出来ます。
アプリは、Chromeのwebストアから無料でダウンロードが可能です。

エディタの画面上で矩形や画像、表を配置することが出来るので、
全てソースから作成するより、PDFの出来上がりが想像しやすいです。
また、要素の座標位置も1px単位で確認できるので、微調整も容易です。

enter image description here

矩形は四角と丸、直線のみですが、細かく調整が可能なため、
組み合わせれば、PDF上に簡単なイラストを描くことも可能です。
この辺りはペイントやパワーポイントで使用できる矩形を想像してもらえれば、
操作性が想像しやすいかと思います。


2. 要素の流し込みが簡単

エディタには矩形とは別に、要素の流し込み先となる枠(テキスト・画像)を作成できる機能が組み込まれています。
流し込み先をレイアウトファイル内に作ってしまえば、あとはrails側で要素を投げるだけでPDFに内容を埋め込めます。

enter image description here

また、Thinreports用のgemがあるので、rails側のセットアップも比較的簡単です。
Gemfile内にgem thinreportsを記述してbundle installすれば、事前準備は完了です。
あとは、コントローラなどからレイアウトファイルに値を渡してあげましょう。
enter image description here

上のコードは、先程のレイアウトファイルに要素を渡し、PDFを出力している所です。
Userモデルの情報をpdf化しています。
値の受け渡しは、基本的にvalueで渡せますが、画像の場合はsrcを使って、画像のパスを渡せばOKです。

欠点

1. 流し込む要素が大きいと対応しにくい

一つの流し込み領域に対して、長いテキストなどを入れる場合、
領域からはみ出すぶんに関して、
「その分領域を拡張する」「文字サイズを縮小する」のどちらかを選択しておくことが出来ます。
ただし、拡張されるのはその領域だけなので、すぐ下に別のテキスト等があると、表示がかぶってしまいます。
文字を縮小すればかぶりませんが、縮小した所だけ不自然に文字が小さくなってしまうので、要素の規定文字数が定まっていない場合、あまり向かないかもしれません。


2. フォントが少ない

enter image description here

細かい所ではありますが、エディタで使用できるフォントが少ないです。
日本語のフォントは「明朝体」「ゴシック体」の二つのみです。
このフォントは流し込みをした要素にも適用されるので、
多様にフォントを使用して、デザインの凝ったPDFを作成したい、という場合は別の方法を取った方がいいでしょう。
一応、開発元のロードマップには、カスタムフォント対応が予定されていますが、
更新の頻度が低いようなので、あまり期待せず待つしか無いようです・・・



以上、Thinreportsを使ってみた感触でした。
目的によって向き・不向きがありますが、視覚的にレイアウトが作れて、
結構きれいなPDFが出力できるので、気になった方は一度触ってみるのも良いかもしれません。

MySQLの出力結果をファイルに出力

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

業務上、UT、IT等でデータベース値とテストシナリオ期待値を見比べる機会があり、
MySQLクライアントで値を見るのに手間を感じ、MySQLの結果をファイル出力出来ないか調べました。

MySQLの出力結果をファイルにはきだしたいとき

mysql> SELECT * FROM [table] INTO OUTFILE "[file]" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '[クォート文字]';

ただし、この方法で指定するCSVファイルの出力パスは、
DBサーバー側のファイルパスを指しています。
そのため、サーバーとクライアントのホストが異なる場合は、
クライアントホストのファイルパスを探しても、CSVファイルは出力されていません。

CSVファイルに出力するコマンド

MySQLクライアント使わない方法もありました。

mysql -u [ユーザー名] -p -h [DBサーバーホスト名] [DB名] -e "`[実行SQL]`" | sed -e 's/\t/,/g' > [出力CSVファイルパス]

このコマンドで、リモートDBの結果をローカルCSVファイルに出力できます。

最近人気な記事