2019年9月15日日曜日

macOS 10.14.6 に Ruby 2.0.0 をインストールする方法

概要

Homebrew でインストールした場合は最新のバージョンが入ります
古いバージョンの Ruby を使いたい場合は rbenv を使うと楽です

環境

  • macOS 10.14.6

rbenv インストール

  • brew install rbenv

rbenv を使って Ruby 2.0.0 をインストール

  • export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  • export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include
  • rbenv install -l
  • rbenv install 2.0.0-p645

ruby-buildopenssl が必要になるのでない場合は

  • brew install ruby-build openssl

しましょう

使う

  • /Users/hawksnowlog/.rbenv/versions/2.0.0-p645/bin/ruby -v

メインの Ruby にする

Homebrew ではなく完全に rbenv に移行する場合は以下のようにします

  • rbenv init - >> ~/.bash_profile
  • source ~/.bash_profile

一番後ろに追記しているので PATH に最優先で探索されます
Homebrew の Ruby の PATH は削除しないでも大丈夫です
元に戻す場合は ~/.bash_profile の内容を元に戻しましょう

2019年9月12日木曜日

numberOfRowsInSection unrecognized selector sent to instance

概要

Xcode でビルドした際にタイトルのようなエラーが出ました
StoryBoard で Outlets などを使っている場合に出るようです

環境

  • macOS 10.14.6
  • Xcode 10.3

エラー文

2019-09-11 16:35:13.649217+0900 ios-fndic[16100:1943401] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ios_fndic.FirstViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x7f9d4d83a800'

対応方法

StoryBoard の Outlets をちゃんと設定するという記事をよく見たのですが自分の場合は違いました
ViewController クラスでちゃんと UITableViewDelegateUITableViewDataSource を継承して上げる必要がありました

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, ...

参考サイト

2019年9月11日水曜日

No such module RealmSwift

概要

いつも対処方法を忘れるのでメモ

環境

  • macOS 10.14.6
  • Xcode 10.3

対処方法

Pods -> RealmSwift -> Build Settings -> Build Active Architecture Only -> No

もしくは

Pods -> Pods -> Build Settings -> Build Active Architecture Only -> No

上記以外にも試す価値あり

  • rm -rf Pods
  • pod update

そして Xcode を再起動します

2019年9月10日火曜日

どんなときも Wifi レビュー

概要

1 ヶ月ほど使ったので備忘録として残しておきます

Good

通信制限がない

100GB 制限とか 3 日で 7GB 制限などはないので常時出せるだけ出してくれます

速度は平均 10Mbps くらい

平均すると 10Mbps くらいは常時でます
平日昼間の空いている時間がおそらくピークで 20 - 30 Mbps は出ます
夜のゴールデンタイムはやはりベストエフォートなのか 1 - 5Mbps くらいしか出ないときもザラにあります
ですが 128kpbs などのよくある通信制限状態になることはありません

Bad

クラウド SIM なので障害がある

2019/08/31 - 2019/09/03 あたりで公式からアナウンスもあったのですがクラウド SIM なのでクラウド側に障害が発生すると通信もできなくなります
頻繁にあるわけではないですがクラウド起因だということを理解しておく必要があります
公式でどのクラウドを使っているなどの紹介はありませんが障害の発生日時などを照らし合わせるとある程度は絞り込めるかも?

Mac App Store に接続できない? -> macOS のアップデートができなかった

最近あった 10.14.6 の追加アップデートができませんでした
D1 というルータに防護機能がありこれを OFF にするとできるという情報があったのですが OFF にしてもダメでした
iOS アプリのアップデートはできたので macOS だけダメなような気がします

キャリアの選択はできない、回線の違による検証とかできたらよかった

仕様では「最適」なキャリアを選択するとあるのですがこれを自分で選択することはできません
docomo or au or Softbank なのですが例えばキャリアの違いによる検証をしたい場合に手動で切り替えたりはできません
日常使いする分には手動で切り替える必要全くないですが機能としてあると嬉しいなと思った感じです

D1 がダメ

同時接続が「5台」しかないのが最大の痛手です
自分はラズパイを一つ使って hostapd でアクセスポイントを増やしています (参考)
これだと無限に接続できますがラズパイのスペックがある程度要求されるのでご注意ください
また記事でも書いていますがラズパイ経由の通信は速度が 1/10 くらいになってしまうので正直限られたことしかできないです

あとはルータとしての機能もそこまで多くないです
Static Routing やポートフォーワド、VPN パススルーのような機能はなかった気がします

契約に縛りあり

2 年契約です
2 年後は割引も解消されてしまいます
そのタイミングで乗り換えを検討するのはありだと思います

月間の利用容量がわからない

ルータによっては月間でどれくらい使用したかわかるのですが D1 にはないようです
毎日リセットされる?っぽいので自分で忘れずにメモして管理するしかなさそうです

最後に

どんなときも Wifi を 1, 2 ヶ月使ってみた感想を紹介しました
完璧なポケット Wifi は現状ないのでそれを求めてはダメですが現行のポケット Wifi の中ではかなり良い方だと思います
月額料金も他のポケット Wifi と変わりません 
特に通信制限がないのはかなり良いです
ただ速度自体がそこまで出ないので速度を求める場合にはあまりおすすめしません
特にリアルタイムゲームなどをやる場合にはちゃんと固定回線を引きましょう

2019年9月6日金曜日

Sass 超入門

概要

Sass は CSS をプログラマブルに書けるツールです
Sass 形式で書いたファイルを CSS にコンパイルすることで使えるようになります
今回はインストールから簡単なサンプルコードいろいろと実装して実際に動かして試してみました
また Ruby 版の Sass は廃止になり Dart 版が現在はサポート対象なので Dart 版を使います

環境

  • macOS 10.14.6
  • Sass (Dart) 1.22.10

インストール

  • xcode-select --install
  • brew install sass/sass/sass

xcode-select が必要になるのでない場合はインストールしましょう
また Ruby 版の sass がすでにある場合は今回インストールした dart 版で上書きしましょう

  • rm /usr/local/bin/sass
  • brew link sass

テスト用のアプリの作成

なんでも OK です
静的ファイルを配信するだけなので nginx の DocumentRoot でも OK です
今回は Sinatra アプリを作成します

  • bundle init
  • vim Gemfile
gem "sinatra"
  • bundle install --path vendor
  • vim app.rb
require 'sinatra/base'

class Sass < Sinatra::Base
  get '/' do
    erb :index
  end
end
  • vim config.ru
require './app'

run Sass
  • mkdir public
  • mkdir views
  • vim views/index.erb
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="/test.css">
  </head>
  <body>
    <div id="message">hello
      <div class="nested">world</div>
    </div>
  </body>
</html>
  • bundle exec rackup config.ru

localhost:9292 でアプリで起動します
コンパイルした CSS ファイルは public ディレクトリ配下で配信します

とりあえずコンパイルしてみる

兎にも角にも .sass ファイルコンパイルして .css ファイルを作成してみましょう

  • vim test.sass
#message
  font-size: 24px

ブラケットなどは不要でインデントを使います
あとは sass コマンドを使ってコンパイルします

  • sass test.sass public/test.css

基本的な使い方は sass [input sass file] [output css filie] になります
.css ファイルの他に .css.map というファイルも作成されます
map ファイルは元の sass ファイルがどこにあるのかを記録しておくフィアルになります
これ以外にもたくさんオプションがあるので詳しくは --help オプションで確認してください
(以下同じコマンドでコンパイルするので省略します)

これでアプリを起動して確認してみましょう
先ほどと違ってフォントサイズが大きくなっているのが確認できると思います

変数を使う

スタイルシートで同じ値を使い回すことは多いと思います
変数はいろいろなケースで使えます

$fs: 24px

#message
  font-size: $fs

入れ子にする

階層になっている場合には入れ子として宣言できます

$fs: 24px

#message
  font-size: $fs
  .nested
    color: #13f304

id 属性や class 属性に関してはそのまま使えます

import

複数の .sass ファイルに分けて管理することができます
部分ファイルはアンダースコアから始まるようにしましょう

  • vim _partial.sass
.nested
  margin: 10px
  • vim test.sass
@import 'partial'

$fs: 24px

#message
  font-size: $fs
  .nested
    color: #13f304

@import 'partial' という感じで指定します
import する partial ファイルのアンダースコアは省略できます

ポイントなのは最終的に出力される .css ファイルは import した partial ファイルの順番になります
そして .css は後にかかれている定義が優先的に評価されます
なのでもし test.sass.nestedmargin を再定義している場合はそちらが優先されることになります

四則演算

サイズなどは四則演算が使えます

@import 'partial'

$fs: (24px - 12px)
$width: (100% - 20%)

#message
  width: $width
  font-size: $fs
  .nested
    color: #13f304

基本的には同じ単位でやるのでいいでしょう
パーセントと組み合わせて使うこともできます
ただ (24px - 50%) などはエラーになります

関数

独自の関数も定義できます
引数に応じていろいろと定義を変えたい場合に便利です

@import 'partial'

@function double($value)
  @return $value * 2

$fs: (24px - 12px)
$width: (100% - 20%)

#message
  width: $width
  font-size: $fs
  .nested
    color: #13f304
    font-size: double($fs)

複雑になってきましたが上記は double という関数を定義しています
(24px - 12px) = 12px を渡してそれを倍にした値を font-size にしています
ビルトインの関数もいろいろとあるのでこちらを参照してください

@mixin

関数に似た機能ですが定義したスタイルを別のスタイルに @include することができます

@import 'partial'

@function double($value)
  @return $value * 2

@mixin margin-reset
  margin: 0px

$fs: (24px - 12px)
$width: (100% - 20%)

#message
  width: $width
  font-size: $fs
  .nested
    color: #13f304
    font-size: double($fs)
    @include margin-reset

@mixin で定義して @include で参照します
同じような機能に @extend という機能もあります
どちらがどう使うかはこのあたりの記事が参考になるかもしれません

最後に

Sass に入門してみました
Ruby 版が廃止になったので Dart 版を使っています
変数や関数を使ってごちゃごちゃになった CSS をキレイに書くことができると思います
面倒なのはコンパイルする必要がある点なのでビルドフローがあれば忘れないように入れるようにしましょう
また --watch という機能もあるので更新するたびにコンパイルすることもできます

まだ Web 上には Ruby 版の情報がちらほらあるのでドキュメントは基本的に公式のものを使いましょう

参考サイト

2019年9月5日木曜日

golang で環境変数のデフォルト値を設定する方法

概要

Ruby で言うところの

v = ENV['VALUE'] || 'hoge'

です

環境

  • macOS 10.14.6
  • golang 1.12.9

サンプルコード

専用の関数を作成すれば OK です

package main

import (
    "fmt"
    "os"
)

func getEnv(key, fallback string) string {
    if value, ok := os.LookupEnv(key); ok {
        return value
    }
    return fallback
}

func main() {
    v := getEnv("VALUE", "fuga")
    fmt.Println(v)
}

参考サイト

2019年9月4日水曜日

go-workers で SIGINT や SIGHUP のシグナルをハンドリングする方法

概要

go-workers でシグナルをハンドリングする方法を紹介します

環境

  • macOS 10.14.6
  • go 1.12.9
    • go-workers dbf81d0b75bbe2fd90ef66a07643dd70cb42a88a

go-workers 内でハンドリングしてくれるシグナル

実は go-workers 内でも特定の Ctrl+c などのシグナルはハンドリングしてくれています

func handleSignals() {
        signals := make(chan os.Signal, 1)
        signal.Notify(signals, syscall.SIGUSR1, syscall.SIGINT, syscall.SIGTERM)

        for sig := range signals {
                switch sig {
                case syscall.SIGINT, syscall.SIGUSR1, syscall.SIGTERM:
                        Quit()
                }
        }
}

この関数はワーカーが Run() した際に goroutine として実行されています
Ctrl+c は syscall.SIGINT になります
やっていることは単純で Quit() という処理を実行してワーカーが正しく終了されるような処理を実行しています

ただ SIGHUP などはハンドリングしていないのでワーカーに SIGHUP を送信すると「Hungup: 1」と表示されて終了してしまいます
しかも go run で実行しているとビルドのプロセスが残ってしまい面倒なことになります
なので他のシグナルも本当はちゃんとハンドリングしてあげる必要がありそうです

SIGHUP をハンドリングしてみる

試しに SIGHUP を追加でハンドリングできるようにしていみます
特にライブラリに手を入れる必要はなくワーカー側でハンドリングするようにすれば OK です

package main

import (
    "os"
    "os/signal"
    "syscall"

    "github.com/jrallison/go-workers"
)

func handleSignals() {
    signals := make(chan os.Signal, 1)
    signal.Notify(signals, syscall.SIGHUP)
    for sig := range signals {
        switch sig {
        case syscall.SIGHUP:
            workers.Logger.Println("sighup")
        }
    }
}

func perform(msg *workers.Msg) {
    c, _ := msg.Args().Int()
    for i := 0; i < c; i++ {
        workers.Logger.Println(i)
    }
    workers.Logger.Println("end")
}

func main() {
    workers.Configure(map[string]string{
        "server":  "localhost:6379",
        "process": "1",
    })
    workers.Process("default", perform, 1)
    go handleSignals()
    workers.Run()
}

handleSignals 関数をそのまま使って syscall.SIGHUP をハンドリングできるようにします
また main() 内で Run() する前に goroutine として関数を実行しておきます

動作確認

ワーカーを起動して SIGHUP シグナルを送信してみましょう

  • go fmt ./... && go build worker.go && ./worker
  • kill -SIGHUP `ps aux | grep './worker' | grep -v grep | awk '{print $2}'`
workers: 2019/09/04 09:15:55.161765 processing queue default with 1 workers. workers: 2019/09/04 09:15:59.230297 sighup

こんな感じで表示されます
またハンドリングしていない場合はプロセス自体が終了していたのですが今度は終了しなくなったと思います

SIGINT を独自にハンドリングしてみる

go-workers 側で SIGINT をハンドリングしていますが自信でもハンドリングしたいケースはあると思います
先程のワーカーの handleSignals 関数に syscall.SIGINT も追加してみます

func handleSignals() {
    signals := make(chan os.Signal, 1)
    signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT)
    for sig := range signals {
        switch sig {
        case syscall.SIGHUP:
            workers.Logger.Println("sighup")
        case syscall.SIGINT:
            workers.Logger.Println("sigint")
        }
    }
}

動作確認

  • go fmt ./... && go build worker.go && ./worker
  • kill -SIGINT `ps aux | grep './worker' | grep -v grep | awk '{print $2}'`
workers: 2019/09/04 09:32:23.858982 processing queue default with 1 workers. workers: 2019/09/04 09:35:47.852373 sigint workers: 2019/09/04 09:35:47.852375 quitting queue default (waiting for 0 / 1 workers).

ちゃんと SIGINT を独自でハンドリングできました
が、独自のハンドラを抜けてライブラリ側のハンドラーにも行ってしまうようでワーカーは終了してしまいました
たぶん golang の仕様だと思うのですがシグナルのハンドラが複数 goroutine で動いている場合はすべての goroutine がシグナルをキャッチできるんだと思います

なので使い方としては SIGINT の終了前に何か処理をしたい場合に使う感じかなと思います

最後に

go-workers でシグナルをハンドリングする方法を紹介しました
コードを見ると AfterQuit という関数がコメントアウトされていたので始めはミドルウェア的な使い方でハンドリングできるのかなと思ったのですがどうやらダメそうです
今回紹介した方法はライブラリ側でシグナルハンドリングが行われる前に何かする方法になります
なのでライブラリ側で処理した後に何かしたい場合は直接コードを書き換えるしかなさそうで