woshidan's loose leaf

ぼんやり勉強しています

esaやGitHubに検証結果貼りつけたいが、 tableタグや img タグなど書くのが面倒な時用のスニペット

esaGitHubに検証結果貼りつけたいが、 img タグなど書くのが面倒な時用のスニペット

出力用コード

require 'yaml'
require 'erb'

puts ARGV[0]

file    = File.open ARGV[0]
raw_str = file.read
@tests  = YAML.load(raw_str)

template_path = File.expand_path('template.erb', File.dirname($0))
erb = ERB.new(File.new(template_path).read)

puts erb.result(binding)

erbテンプレート

<!-- HTML -->
<% @tests.each do |test| %>

<h3><%=  test["title"] %></h3>

<table>
   <tr>
      <td>
      </td>
        <%  test["rows"].each do |row| %><th>
                <%= row %>
            </th><% end %>
  </tr>
    <% test["cols"].each do |col| %><tr>
        <th>
            <%= col %>
        </th>
      <%  test["rows"].each do |row| %><td>
          <% if test["with_image"] %>
            <img src="" alt="<%= "#{col} x #{row}" %>" width="<%= test["image_width"] %>px" />
            <% end %>
        </td>
      <% end %></tr>
    <% end %>
</table>

<% end %>
# Markdown
<% @tests.each do |test| %>

### <%=  test["title"] %>

|   <%  test["rows"].each do |row| %>|<%= row %><% end %>|
|---<%  test["rows"].each do |row| %>|---<% end %>|
<% test["cols"].each do |col| %>|<%= col %><%  test["rows"].each do |row| %>|<% if test["with_image"] %> <img src="" alt="<%= "#{col} x #{row}" %>" width="<%= test["image_width"] %>px" /><% end %><% end %>|
<% end %>
<% end %>

使い方

$ ruby build_table.rb sample.yml 

入力として用意するYAML

- with_image: true
  image_width: 100
  title: AとBの条件についてテスト(要スクショ)
  rows:
    - A = 1
    - A = 2
    - A = 3
    - A = 4
    - A = 5
  cols:
    - B = 1
    - B = 2
    - B = 3
- with_image: false
  title: AとBの条件についてテスト(スクショ不要)
  rows:
    - A = 1
    - A = 2
  cols:
    - B = 1
    - B = 2
    - B = 3
    - B = 4

出力

HTML

<h3>AとBの条件についてテスト(要スクショ)</h3>

<table>
   <tr>
        <td>
        </td>
        <th>
                A = 1
            </th><th>
                A = 2
            </th><th>
                A = 3
            </th><th>
                A = 4
            </th><th>
                A = 5
            </th>
    </tr>
    <tr>
        <th>
            B = 1
        </th>
        <td>
            
              <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/woshidan/20171018/20171018132818.png" alt="B = 1 x A = 1" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 1 x A = 2" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 1 x A = 3" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 1 x A = 4" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 1 x A = 5" width="100px" />
            
        </td>
        </tr>
    <tr>
        <th>
            B = 2
        </th>
        <td>
            
              <img src="" alt="B = 2 x A = 1" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 2 x A = 2" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 2 x A = 3" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 2 x A = 4" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 2 x A = 5" width="100px" />
            
        </td>
        </tr>
    <tr>
        <th>
            B = 3
        </th>
        <td>
            
              <img src="" alt="B = 3 x A = 1" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 3 x A = 2" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 3 x A = 3" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 3 x A = 4" width="100px" />
            
        </td>
        <td>
            
              <img src="" alt="B = 3 x A = 5" width="100px" />
            
        </td>
        </tr>
    
</table>



<h3>AとBの条件についてテスト(スクショ不要)</h3>

<table>
   <tr>
        <td>
        </td>
        <th>
                A = 1
            </th><th>
                A = 2
            </th>
    </tr>
    <tr>
        <th>
            B = 1
        </th>
        <td>
            
        </td>
        <td>
            
        </td>
        </tr>
    <tr>
        <th>
            B = 2
        </th>
        <td>
            
        </td>
        <td>
            
        </td>
        </tr>
    <tr>
        <th>
            B = 3
        </th>
        <td>
            
        </td>
        <td>
            
        </td>
        </tr>
    <tr>
        <th>
            B = 4
        </th>
        <td>
            
        </td>
        <td>
            
        </td>
        </tr>
    
</table>

esaに貼り付けてみたときの見た目

f:id:woshidan:20171018133017p:plain

画像入れてく部分は画像が入ってなかったらaltに条件の文字列入れてるのでどの条件のテスト終わってないかわかりやすい。

XCodeのRun Scriptを試しに触ってみる

iOS用アプリケーション、ライブラリのビルド前後にちょっと作業がしたい場合、XCodeRun Script でシェル(やシェル経由で起動できる各種言語のプログラム)を起動させることができます。

今日はちょっと試してみました。

簡単なスクリプトの実行

# hello.sh
echo "hello"

こういう超簡単なスクリプトを用意して、

f:id:woshidan:20171018004411p:plain

f:id:woshidan:20171018004429p:plain

上図のように、実行したいスクリプト hello.sh のパスを設定すると、ビルド時のログに hello と出力されます。

f:id:woshidan:20171018004455p:plain

スクリプトのパスを指定する代わりにそのまま書く

以下のようにそのまま実行したいスクリプトをベタがきすることも可能です。

f:id:woshidan:20171018004826p:plain

上記を実行すると

f:id:woshidan:20171018004851p:plain

ちょっとビルド自動化の際など環境変数を調べたいときに便利そうです。

指定したファイルのパスを変数に与えて実行

下の方の欄にある input files にファイルのパスを与えると、スクリプト中にて $SCRIPT_INPUT_FILE_N (Nは数字) という変数名で取得可能です。ちょっとやってみましょう。

// Test.xcodeproj/project.pbxprojの冒頭
// !$*UTF8*$!
{
    archiveVersion = 1;
    classes = {
    };
    objectVersion = 48;
    objects = {

f:id:woshidan:20171018005207p:plain

f:id:woshidan:20171018005216p:plain

出力結果の2行目はビルド時に書き加えられたものです。 Run Script の中に書いたスクリプトや実行ファイルのパスは XCode のプロジェクト設定ファイルの中に記録され、管理されます。

スキームごとに接続先などを変更したいけど、コードの中に残したくない、という場合*1などに置換処理を行ったりできるのではないでしょうか。

現場からは、以上です。

参考

*1:書いてみたけどコードの中に残した方が人間が読む上で素直な気がする

今日のAWS

AWS ELB

  • オンプレでいうロードバランサ
  • 配下のインスタンスのヘルスチェックやそれに基づいた振り分けの停止/再開・暗号化/復号化(SSL)機能あり

ELBのメリット

  • 複数AZに対して分散を行える。1つのAZがオフラインになった場合でももうひとつのAZで処理を続けられる
  • HTTPS/SSLを利用できる
  • 正常なインスタンスのみ振り分け可能
  • ユーザセッションを維持する スティッキーセッション をサポート
    • ご存知ない用語だった。ロードバランサーがユーザーのセッションを特定のappサーバへ振り分けるよう固定する機能で、これによりユーザのセッション中の全てのリクエストが同じインスタンスへ送信される(スティッキーにする期間は指定可能)
  • セキュリティグループポリシーを適用でき、柔軟なセキュリティを実現できる

AZ(アベイラビリティーゾーン)って何?

  • AWS(EC2)のロケーションは、リージョンとアベイラリティゾーンという概念がある
    • リージョンは、東京, バージニア, サンパウロ, ソウル...
      • リージョンによって ap-northeast-NN の部分が変わる。東京は N=1
    • アベイラリTゾーンというのは、同一リージョン内の独立したロケーションの単位(データセンターの単位を想定すると大体あってる)
      • たとえば東京リージョンに ap-northeast-1a, ap-northeast-1b, ap-northeast-1c の3つのAZがある
      • なんとなくで特定のアルファベットのAZの利用が偏らないように、アカウントごとにどこのデータセンタが a, b, c のどれにあたるのかは異なるらしい

DNSのCNAMEってなんだっけ

  • Aレコードは ドメイン名と対応するIPアドレスドメイン名:IPアドレス = 1:n で定義
    • 同じIPと別ドレインを並べて定義すれば IPアドレス:ドメイン名 = 1:n にもなりうる
  • CNAMEレコード
    • CNAMEレコードはすでにAレコードで定義されてるドメイン名と別名を定義
      • メイン名1:IPアドレス1(これらの対応は1:1)、と定義がある時、
      • と書くことで IPアドレス:ドメイン名 = 1:nを定義することができる

参考

iOSアプリをxcodebuildでビルドする(途中)

Appiumの前段階として、Simulatorなどにインストールするビルド済みのAppファイル*1*2が必要です。

メモ

そういうわけで、ターミナルから xcodebuild を使って Appファイル の作成を試します。

$ xcodebuild
xcodebuild: error: The directory /Users/woshidan/path/ios-project/root/ does not contain an Xcode project.

$ cd path/to/XcodeProject

$ ls
TestApp         TestApp.xcodeproj       TestAppUITests          build

まずは、 XCodeで作成したプロジェクトのあるところ( .xcodeproj ファイルのあるディレクトリ ) へ移動します。

依存しているライブラリのクラスのヘッダが見つからない ...

xcworkspace など依存ライブラリの設定が入ったファイルを、 -workspace で指定しましょう。その際、 schema も指定が必要です。

// # CocoaPodsを使っていてxcworkspaceを指定してビルドする
$ xcodebuild -workspace ../../Test/TestLib.xcworkspace -scheme TestApp

CompileStoryboard TestApp/Base.lproj/Main.storyboard というメッセージが出てStoryBoardがビルドできない

Xcode のバージョンによっては、特定の設定がないとビルドができないものがあります。そう、古い設定は新しいXCodeのバージョンが出るたびにビルドできなくなる可能性があるのです*3

というわけでそういう場合は、xcodebuildで利用するXCodeのパスを古いものに xcode-select で切り替えます。

# xcode-select -s /Applications/__oldXcode.app/Contents/Developer

シミュレータでビルドしてもらうよう指定する

-sdk iphonesimulator オプションを追加してビルドします。

$ xcodebuild -workspace ../../Test/TestLib.xcworkspace -scheme TestApp -sdk iphonesimulator

のはずなんですが、めっちゃいっぱい ❌ /Applications/__oldXcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.3.sdk/usr/include/sys/_types.h:76:9: unknown type name '__uint32_t'; did you mean '__uint128_t'?

が出てつらいんで解決したらまたなんか書こう...。

*1:.appファイルはXCodeでビルドが完了すると $(PROJECT_DIR)/build/Release-iphoneos/xxxxx.app のようなパスに作成され、これを Payload フォルダに入れて圧縮 -> 拡張子を変更したものが .ipa ファイル https://developer.apple.com/jp/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html http://lain.heavy.jp/lain/2012/01/13/462 参照

*2:appiumのcapsファイルに指定するファイルは .ipa でも .app でもよさそう...?

*3:若干、いいすぎですが、メジャーバージョンが2~3離れたりしたら厳しい

今日のbash

& ... コマンドをバックグラウンドで実行する

参考: http://itpro.nikkeibp.co.jp/article/COLUMN/20060224/230589

$ heavy_command&

case 文 ... 他の言語のswitch と同じ

参考: http://shellscript.sunone.me/case.html

  casein
    パターン1 ) 処理1;;
    パターン2 ) 処理2 ;;
    パターン3 ) 処理3 ;;
    …
    パターンn ) 処理n ;;

) の記法がマジでびびる。

getopts

参考: https://www.ibm.com/support/knowledgecenter/ja/ssw_aix_71/com.ibm.aix.cmds2/getopts.htm https://qiita.com/b4b4r07/items/dcd6be0bb9c9185475bb

コマンド・ラインの引数を処理し、有効なオプションを検査する。

こないだrubyでちょいとしたスクリプト書いてる時に引数検査をARGVでeach回してぐるぐるしてたんですけど、 あったわ〜 シェルにあったわ〜 って感じです。

getopts OptionString Name [Argument...]

OptionString は、使用したいオプションの文字列。よくある例としては hhelp で使い方を出力する、といったもの。

: をつけるかどうかで振る舞いが変わり、 OptionString の後ろに : をつけると、そのオプションは引数を必要とするようになります。

指定していないオプションや引数を使った場合に

# https://qiita.com/b4b4r07/items/dcd6be0bb9c9185475bb より引用
./test.sh: option requires an argument -- d
./test.sh: illegal option -- x

のようにエラー表示が出て終了しますが、 OptionString の全体の前に : をつけるとこのエラー表示は行われなくなり、自前でのエラー処理を行うことができます。

https://qiita.com/b4b4r07/items/dcd6be0bb9c9185475bb の記事が非常に参考になり、 getopts のテンプレートなども紹介されているので今度便利コマンドを使う時は利用したいところです。

$! ... 最後に実行されたバックグラウンドコマンドのプロセスIDに展開

参考: https://qiita.com/laikuaut/items/1daa06900ad045d119b4

ちなみに現在動かしている(バックグラウンドでない)シェルのプロセス番号は $ で展開される。

$ echo $$
521

会社のrubyのバージョンが2.4.0以降にあげられないので `Array#-` と同等のスニペットをおいておく

irb(main):010:0>   class Array
irb(main):011:1>     def - other
irb(main):012:2>       copy = self.dup
irb(main):013:2>       other.each do |other_array_item|
irb(main):014:3*         copy.delete other_array_item
irb(main):015:3>       end
irb(main):016:2>       copy
irb(main):017:2>     end
irb(main):018:1>   end
=> :-
irb(main):019:0> a = [1, 2, 3]
=> [1, 2, 3]
irb(main):020:0> b = [1, 2, 4]
=> [1, 2, 4]
irb(main):021:0> a - b
=> [3]

参考

自作クラスのテスト用にComparableモジュールと宇宙船演算子を使って同じオブジェクトか比較しやすくする

rubyでちょっとした処理を担当する自作クラスのテストをするとき、同じオブジェクトがどうかの比較する際、

assert_equal expect_obj.hash_value, actual_obj.hash_value # hash_valueはオブジェクトのidではないオブジェクトに特有の値

というような式をよく書いていました。ですが、そんなに広く使われないクラスであることがわかっているなら == 演算子の挙動をいじってしまって、

assert_equal expect_obj, actual_obj

とかけるようにしちゃっていいかも、ということでその方法をメモ。

class MyClass
  include Comparable # 宇宙船演算子の内容を元に `<=`, `>=` を使えるようにしてくれる

  def <=> other # 宇宙船演算子を使って、`<`, `==`, `>` 用の動作を定義
    return nil unless other.is_a? MyClass
    hash_value <=> other.hash_value # MyClassのオブジェクトが同一かどうか判断するための比較に、hash_valueの比較を使う
  end

  def hash_value
    # テストでも作りやすい値を元にハッシュ値を計算する
  end
end

参考

Effective Ruby

Effective Ruby