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を指定するだけです。
... "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)構成でやります。
環境
インストール
$ 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を試しに入れてみます。
yum
やservice
がモジュールにあたる部分です。
他のモジュールは公式ドキュメントの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/mofumofu3n
のmofumofu3n
に当たる部分が: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による書き方を学ぶこと。なので、実際に品質が担保できているかは今回見ない
テストの対象は昨日書いた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日目)
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の引数
f
がgets
メソッドを持っていなかった場合、fをファイル名とみなしファイルオープンする。
chopメソッド
文字列の末尾から1文字取り除いた文字列を返す
ruby始めてみた(1.0+1.0日目)
日曜くらいからrubyを触り始めました。
そもそもなぜ今更rubyを始めたのか。 理由は3つです。
特にやりたいことは決まっていないので、思いついたことをやっていきます。
最初はお馴染みのFizzBuzzをやって、rubyの文法に慣れていこうと思います。
FizzBuzzとは
プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は 「Fizz」(Bizz Buzz の場合は 「Bizz」)、5で割り切れる場合は 「Buzz」、両者で割り切れる場合は 「Fizz Buzz」 (Bizz Buzz の場合は 「Bizz Buzz」)を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。
要件
- 表示について
- 数字の最大値
実装
それでは実装していく
#!/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ページありましたら教えていただけると幸いです。
参考
- オブジェクト指向スクリプト言語 Ruby リファレンスマニュアル
- [初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか
- コーディング規約をまとめてみた (Ruby編)
環境構築はこちらを見ました