React Nativeのバージョンアップによるreact-navigationでエラーが起きたときの対処方法

React Nativeは2週間に1度のペースでアップデート(早い時は3日に1度のペース)しているので、利用しているライブラリがアップデートに追いつかず壊れるときがしばしばあります。

React Nativeのドキュメントで推奨されているナビゲーション実装のreact-navigationもその一つでReact Nativeのアップデートに伴いエラーが発生しました。

今回は現時点(2017年4月25日時点)での解決方法を書きます。

環境

  • react: 16.0.0-alpha.6
  • react-native: 0.43.4

解決方法は簡単でpackage.jsonのバージョン指定にreact-nativeのコミットIDを指定するだけです。

github.com

...
"dependencies": {
    "react": "16.0.0-alpha.6",
    "react-native": "0.43.4",
    "react-navigation": "git+https://github.com/react-community/react-navigation.git#5905501"
  },
...

issueの中にはリポジトリをそのまま指定する方法もありますが、その場合だと常に最新版を参照するため いつ壊れてもおかしくない状態になります。

ですので、コミットIDを指定して固定しておくのが安全です。

phpカンファレンスでAnsible良さそうって聞いたので調べてみた

phpカンファレンスに参加した際に「Ansible ではじめるサーバ作業の自動化」を見た友人からAnsible良さそうって聞いたので調べてみた。

Ansibleについて

  • 構成管理ツールの一種
  • 他にchef,Puppetがある
  • Pythonで書かれている
  • だからといってPythonの知識は必要ない
  • 対象にAnsibleをインストールする必要がない
  • sshで命令しているため

分類

  • サーバ<-クライアント構成(クライアントからサーバに問い合わせるPull方式)
  • Chef, Puppetなど
  • サーバ->クライアント構成(サーバからクライアントに命令するPush方式)
  • Ansible,Func,Fabric,Capistranoなど

導入のしやすさ

  • ドキュメントが短いため習得が簡単
  • どの言語でもモジュールが書ける

用語

  • モジュール
  • ソフトウェアのインストール、サービスの起動などのクライアント内での動きを定義
  • Python以外の言語で書くことも可能。決められた出力形式であればおけ
  • Play book
  • =レシピ
  • YAML形式で記述
  • inventory file
  • 対象のサーバを管理するファイル
  • グループの指定も可能

導入

ここから実際にAnsibleを使います。 Mac->Vagrant(CentOS 6.5)構成でやります。

環境

  • Mac OS X(10.9.5)
  • Ansible(1.7.2)
  • Homebrew(0.9.5)
  • Virtual Box(4.3.18)
  • Vagrant(1.3.5)

インストール

$ brew install ansible
$ ansible --version
ansible 1.7.2

Vagrantの用意

インストール済み前提に話しを進めます

$ vagrant init
$ vim Vagrantfile
# boxの指定に加え、下記を追記
config.vm.network :private_network, ip: "192.168.33.10"
config.ssh.forward_agent = true
$ vagrant up
$ vagrant ssh-config --host node >> ~/.ssh/config # sshの設定を追記

疎通確認

  • 失敗1
$ ansible 192.168.33.10 -m ping
ERROR: Unable to find an inventory file, specify one with -i ?

接続先を記述したインベントリファイルを用意しないとダメです。

ファイル名はhostsとします。

$ echo 192.168.33.10 > hosts
$ ansible -i hosts 192.168.33.10 -m ping
192.168.33.10 | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue

そして失敗・・・

  • 失敗2
$ ansible -i hosts 192.168.33.10 -m ping
192.168.33.10 | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue

鍵周りかなーと思いつつ、`~/.ssh/configのHostをnodeから192.168.33.10に書き換えます。

$ ansible -i hosts 192.168.33.10 -m ping
192.168.33.10 | success >> {
    "changed": false,
    "ping": "pong"
}

これで成功しました。ansibleはssh経由で対象サーバにアクセスしているため、アクセス時のホスト名で

Play bookを使う

まずはPlay bookを作成します。Play bookは複数のモジュールを定義したファイルです。今回はApacheを試しに入れてみます。

yumserviceモジュールにあたる部分です。

他のモジュールは公式ドキュメントのModule Indexを参照

---
- hosts: 192.168.33.10
  sudo: yes
  tasks:
    - name: be sure httpd is installed
      yum: name=httpd state=installed

    - name: be sure httpd is runnning and enabled
      service: name=httpd state=running enabled=yes

記述後は構文に問題がないか確認します。

ここからは先ほどと変わってansible-playbookコマンドを使っていきます。

$ ansible-playbook -i hosts simple.yml --syntax-check

playbook: simple.yml

問題があれば何かしらエラーを出力します。

では、ansibleを使ってApacheをインストールします。

本来ならインストールする前に--checkオプションを指定してdry-runしておいた方が安全です。今回は省略します。

$ ansible-playbook -i hosts simple.yml
PLAY [test-server] ************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.33.10]

TASK: [be sure httpd is installed] ********************************************
changed: [192.168.33.10]

TASK: [be sure httpd is runnning and enabled] *********************************
changed: [192.168.33.10]

PLAY RECAP ********************************************************************
192.168.33.10              : ok=3    changed=2    unreachable=0    failed=0

192.168.33.10にアクセスするとApacheのテストページを閲覧することができました。

これでPlay bookを利用してソフトウェアのインストールが出来ました。

tips

  • インベントリファイルの指定を省略する

毎回インベントリファイルを指定するのが面倒な場合はansibleの設定ファイルに記述すると省略できます。

ansible.cfgを用意して、そこにhostsを指定します。

$ vim ansible.cfg
[defaults]
hostsfile = ./hosts
  • インストール時にターミナルから入力させる

追加するユーザ名を入力させるときは以下のようになる。

vars_promptでユーザーに入力させ、入力された値はusernameに格納される仕組み

またusernameが変数となっており、こちらを利用する場合は{{}}の中に変数名を記述する

vars_prompt:
  username="Enter username"
  tasks:
  - name: add User
    user: name={{username}}

単純に変数を利用する場合は以下のとおり、

vars:
  username: mofumofu3n
  tasks:
   - name: add User
     user: name={{username}}
  • yamlファイルで繰り返しを利用する

例えばphpをインストールする場合、phpだけでなく紐づくソフトウェア(php-mysql)もインストールすることがあります。

そんなときは繰り返しを使うことで複数のソフトウェアを入れることが出来ます。

- name: install php package
  yum: name={{item}} state=latest
  with_items:
    - php
    - php-devel
    - php-mbstring
    - php-mysql

with_itemsで指定したソフトウェアが順次itemに展開され、インストールされていきます。

まとめ

以前、chefを使っていましたが対象サーバにchefを入れる必要があるため、時間がかなり掛かっておりここがネックだなーと思っていました。

Ansibleであればsshで実行しているため、より気軽に開発サーバを作ったり壊したり出来そうです。

また特定言語の知識が必要ないのも嬉しいところです。(といってもYAMLの構文を覚える必要はありますが。。)

YAMLの構文はこちらでまとめられていたので大変参考になります。 * ansible使いのためのYAML入門 - @znz blog

なんにせよ簡単に導入できたのでchefから乗り換えてみようと思います。

参考になりそうなページ

Sinatraでパスによって処理を変更する(ruby勉強6日目)

Qiitaだと一覧性に欠けるので、hatenaに戻しました。

5日目の続きです。

例えば、/hello/mofumofu3nにアクセスした場合、 Hello, mofumofu3nと表示するのを考えます。

この場合は以下の様に実装できます。

get '/hello/:name' do @hello = "Hello Hello, #{params[:name]}!" end

hello/mofumofu3nmofumofu3nに当たる部分が:nameに格納されます。

これのアクセス方法はparams[:name]mofumofu3nにアクセスすることができます。

これだと変数へのアクセスが冗長なので、以下のように変更することもできます。

  get '/hello/:name' do |name|     @hello = "Hello, #{name}!"   end

とりあえずここまで。

#{name}!の「!」って何を表してるんだろ。。。。

Rspecその2(3.0+1.0日目)

昨日の続きで今回は実際にfizzbuzzを判定する部分のユニットテストを書いていきます。

まず、テスト対象が別のメソッドなのでdescribeを分ける。

「メソッドの説明をする」 にしたがってdescribeに説明を書くようにする

describe "#puts_fizzbuzz?" do

end

次はContextsを使うを参考に contextを明確にする。

describe "#puts_fizzbuzz?" do
  context "引数が3の場合" do
  
  end
  
  context "引数が5の場合" do
  
  end
  
  context "引数が15の場合" do
  
  end
  
  context "引数が3,5,15で割れる数以外の時" do
  
  end
end

こんなふうになりました。

で、ここから検証用のコードを書いていきます。

インスタンス生成時の引数は今回不要なため、beforeインスタンス生成の処理 を書いてしまいます。

describe "#puts_fizzbuzz?" do
  before do
    @fizzbuzz = FizzBuzz.new
  end

end

@がつくとインスタンス変数として扱われます。

あとはそれぞれの状態の時のテストを書いていきます。

context "引数が3の場合" do
  it { expect(@fizzbuzz.puts_fizzbuzz 3).to eq :fizz}
end

puts_fizzbuzzではシンボルを返しているので、 シンボルのfizzが帰ってきているか懸賞する

あとは同じように書いていけばおけ。。。

今日は疲れてるので、これで終わり。

そろそろsinatraとかを使ってみたい。

Rspecを使ってテストしてみる(2.0 + 1.0日目)

今日はrubyユニットテスト書いてみる。

目的としてはrubyによる書き方を学ぶこと。なので、実際に品質が担保できているかは今回見ない

テストの対象は昨日書いたFizzBuzzで。

Rspecをインストール

まず、ユニットテストを書くためにrspecをインストールする

$ gem install rspec

Rspecの初期設定

$ rspec --init

これでユニットテストに必要なファイルは揃った。

ファイル構成は以下の通り

次からテストコードを書いていく。

テストコード

specディレクトリにfizzbuzz_spec.rbを作成する。

テストコードのファイルには_specって接尾語を入れるらしい。

#!/usr/bin/env ruby
# encode: utf-8

require "spec_helper"
require_relative "../fizzbuzz.rb"

describe FizzBuzz do
  it "count 10"
    fizzbuzz = FizzBuzz.new
    expect(fizzbuzz.size).to eq 10
end

describeの後ろにはテスト対象のクラスを記述する。

実際に行うテストはit以降に記述する。

expectメソッドにテスト対象クラスのメンバ変数を指定し、 それが実際の値と同じかを検査している。

いざ、これを実行すると見事に失敗する。

失敗の原因はこちら

     Failure/Error: expect(fizzbuzz.size).to eq 10
       
       expected: 10
            got: nil

単純にインスタンスを生成しただけでは、sizeが入らないのでそもそもテストに失敗する。

なので、FizzBuzzクラスを書き換える。

  def initialize(size=10)
    if size.size == 1 && n[0].to_i != 0
        @size = size[0].to_i 
    else
        @size = size
    end
  end

initializeメソッドでsizeを決定するように修正した。

引数に整数が入っていれば、その値を。そうでなければデフォルト値の10が入るようになっている。

これでテストを実行すると、成功!

ついでに値を指定した時のテストもしてみる。

以下をテストコードに追加

  # 30が指定された時に30を返す
  it "count 30" do
    fizzbuzz = FizzBuzz.new 30
    expect(fizzbuzz.size).to eq 30
  end

これも成功!

とりあえず、今日はここまで。

試行錯誤

FizzBuzzクラスが読み込めない

#!/usr/bin/env ruby
# encode: utf-8

require "spec_helper"
require "fizzbuzz"

describe FizzBuzz do
  it "count 10"
  
end

ただ、これだとエラーが表示される。

エラーの内容は以下

`require': cannot load such file -- fizzbuzz (LoadError)

ようは見つからないよってことみたい。

調べてみたところ、こちらが参考になった。

要は実行するときに同じ階層を読み込むがfizzbuzz.rbが同じ階層にないため、エラーしていた。

ファイルの階層を変更するのはちょっと違うので、require_relativeを使えば良いとのこと。

このrequire_relativeは今の位置から相対パスでrequireしてくれる。

単にrequireだとエラーしてしまうので、require_relativeを利用するのが良さそう。

他にもありそうだが、今回は本筋と違うので飛ばす。

参考

【wip】mailread.rb読んでみる(1.0+2.0日目)

前回Rspecやるって書いたけど、ちょっと寄り道。。。

mailread.rbが初心者向けとのことなので読んでみる。

ソースコード

initializeメソッド

class Hoge
  def initialize
  ...
  end
end

defined?

unless

  • 条件式が偽の時に
  • elseを指定することはできない。
    • elseを指定する場合はif文にする。

コードリーディング

最初の部分は以下の通りになる。

def initialize(f)
  unless defined? f.gets
    f = open(f, "r")
    opened = true
  end
  • initializeの引数fgetsメソッドを持っていなかった場合、fをファイル名とみなしファイルオープンする。

chopメソッド

文字列の末尾から1文字取り除いた文字列を返す

ruby始めてみた(1.0+1.0日目)

日曜くらいからrubyを触り始めました。

そもそもなぜ今更rubyを始めたのか。 理由は3つです。

  1. スクリプト言語をちゃんと学びたかった。
  2. インフラ周りのツールrubyで書かれてることが多い。(chefとか)
  3. かなり前から流行ってるじゃん?

特にやりたいことは決まっていないので、思いついたことをやっていきます。

最初はお馴染みのFizzBuzzをやって、rubyの文法に慣れていこうと思います。

FizzBuzzとは

プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は 「Fizz」(Bizz Buzz の場合は 「Bizz」)、5で割り切れる場合は 「Buzz」、両者で割り切れる場合は 「Fizz Buzz」 (Bizz Buzz の場合は 「Bizz Buzz」)を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。

Wikiから

要件

  • 表示について
    • 3で割り切れる時は"Fizz"を表示する
    • 5で割り切れる時は"Buzz"を表示する
    • 3と5で割り切れる時は"FizzBuzz"を表示する
    • それ以外の時は数字を表示する
  • 数字の最大値

実装

それでは実装していく

#!/usr/bin/env ruby
# encoding: utf-8

class FizzBuzz
  attr_reader :size

  def set_max(n)
    @size = self.get_size(n)
  end

  def get_size(n)
    if n.size == 1 && n[0].to_i != 0
      n[0].to_i
    else
      10
    end
  end

  def puts_fizzbuzz(n)
    if n % 15 == 0
      :FizzBuzz
    elsif n % 3 == 0
      :Fizz
    elsif n % 5 == 0
      :Buzz
    else
      n
    end
  end

  def do()
    index = 1
    while index <= @size
      puts self.puts_fizzbuzz(index)
      index += 1
    end
  end

end

fizzbuzz = FizzBuzz.new
fizzbuzz.set_max(ARGV)
puts fizzbuzz.size
fizzbuzz.do

ここで学んだこと

  • クラス定義やメソッド定義は実行前に記述する必要がある。
  • メソッド()は省略可能。ただし、引数が1つの場合のみみたい。
  • セミコロン省略可能。
  • putsで出力する。
  • メソッドの戻り値は最後に評価された値が返る。
  • インスタンス変数は@~
  • attr_readerに指定されたシンボルからインスタンス変数にアクセスできる。
  • クラスの初期化はnewメソッド
  • シンボル文字列は1対1で対応するオブジェクト。そのまま呼び出せば文字列が返ってくる。

こんなところです。

処理に冗長なところもありますが、今はこれでおけ。

次はRspecを利用してユニットテストを書いてみようと思います。

もし、参考になる書籍やWebページありましたら教えていただけると幸いです。

参考

環境構築はこちらを見ました