自宅のubuntu-16.04マシンのシェルをfishに変更した
自宅のubuntu-16.04マシンのシェルをfishに変更したので手順をメモしておきます。
また、pecoとの連携もしていきます。
fish をインストール
sudo apt-add-repository ppa:fish-shell/release-2 sudo apt-get update sudo apt-get install fish
apt-add-repository
コマンドがない場合は以下の手順で導入します。
sudo apt-get install apt-file sudo apt-file update sudo apt-get install software-properties-common
fish をデフォルトシェルにする
追記:
fish はデフォルトシェルにしないほうが良いんじゃないかなー。というのをこちらのエントリーに書きました。 良ければ見てください。 fish をデフォルトシェルに設定しない - takapiのブログ
chsh -s /usr/bin/fish
端末を開き直し、 echo $SHELL
コマンドで確認します。
echo $SHELL /usr/bin/zsh
あれ・・・
GUI環境の場合は一度ログアウトしてあげる必要がありそうです。
echo $SHELL /usr/bin/fish
fishになっていることを確認しました。
fish の基本設定
config ディレクトリを作成します。
mkdir -p ~/.config/fish
初期設定ファイルを作成します。
vim ~/.config/fish/config.fish
~/.config/fish/config.fish
へ以下のようにPATHを追加します。
set -g -x PATH /usr/local/bin $PATH
oh-my-fish をインストール
git がない場合はインストールしておきます
sudo apt-get install git
以下のcurlコマンドで oh-my-fish をインストールします。 ※直接シェルスクリプトを実行するので、中身は必ず確認しておいてください。
curl -L http://get.oh-my.fish | fish
以下のコマンドを打つと、ブラウザが立ち上がり、 fishの設定をGUIで変更できるようになります。
fish_config
私は、 color
をfish default
に prompt
をAcidhub
にしました。
peco をインストール
cd ~ wget https://github.com/peco/peco/releases/download/v0.5.1/peco_linux_amd64.tar.gz tar zxvf peco_linux_amd64.tar.gz sudo cp peco_linux_amd64/peco /usr/local/bin/ sudo chmod 777 /usr/local/bin/peco
peco と fish の連携
こちらの記事を参考にしました。 https://www.key-p.com/blog/staff/archives/105041
pecoプラグインをインストールします。
omf install peco
~/.config/fish/config.fish
に以下を追加します。
#peco function fish_user_key_bindings bind \cr peco_select_history end
コンソールを開き直すなどし、設定ファイルを読み直したあとに Ctrl + r を押すといい感じに履歴とpecoが連携してくれます。
以上で、fish、pecoのインストールは完了です。
参考サイト
fish インストールに関して https://hackercodex.com/guide/install-fish-shell-mac-ubuntu/
pecoのインストールに関して http://qiita.com/popstaplerate/items/dd983267a7075250035b
peco と fish の連携に関して https://www.key-p.com/blog/staff/archives/105041
Rubyのバージョンを上げたときの手順メモ
自端末と自作サービスのRubyのバージョンを2.4.1へ上げたのでそのときのメモを残しておきます。
rbenvとruby-buildの更新
自分はRubyのバージョン管理をrbenvで行っているので、まず、rbenvの更新します。
rbenvを更新
cd ~/.rbenv git pull origin master
ruby-buildを更新
cd ~/.rbenv/plugins/ruby-build git pull origin master
Ruby 2.4.1 をインストール
rbenv install 2.4.1
端末のスペックによってそれぞれですが、結構時間がかかります。
Ruby 2.4.1 を設定
環境全体への設定
rbenv global 2.4.1
自作サービスのRubyバージョンも設定しておきたいので、以下のコマンドで .ruby-version
を作成します。
rbenv local 2.4.1
バージョンが上がっている確認
以下のコマンドでバージョンが上がっているか確認できます。
.ruby-version
があるディレクトリで実行した場合は .ruby-version
で設定されている値が優先されます。
ruby -v ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
以上でRubyのバージョンアップは完了です。
AngularJS1.6に上げたらルーティング時のパスがhash (#/)からhash-bang (#!/)になっていた
AngularJS1.6に上げたらルーティング時のパスがhash (#/)からhash-bang (#!/)になっていた
自己学習用に作成していたAngularJS 1.4アプリをAngularJS 1.6 に上げた際に、
ルーティング時のパスがhash #/
からhash-bang #!/
に変換されるようになってしまい、うまくルーティングが働かなくなってしまう問題に遭遇しました。
対応したのでメモとして残しておきます。
現象
以下のURLに直接またはリンクから遷移しようとしたとき、例えば以下のような
http://localhost:9000/#/search
にすると、ルーティング定義したページを表示して欲しいのですが、
http://localhost:9000/#!/#%2Fsearch
上記のように自動的にスラッシュが %2F
変換され、hash-bang #!/
が追加されます。
自分の環境では、上記のURLはルーティング定義していないので、 otherwise
に設定しているページに遷移されるようになってしまいました。
ちなみに、ルーティングの定義は以下のように行っています。
.when('/search', { templateUrl: 'views/search.html', controller: 'SearchCtrl', controllerAs: 'search' }) .otherwise({ redirectTo: '/' });
原因
AngularJS 1.6が $location
サービスのURLのデフォルト値を変更したことが原因です。
Googleのクローラー対策みたいです。(#!/
を使用することを推奨している。)
ちなみに、以下のコミットで修正されています。 https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52
解決方法1
リンクのURLの#のあとに!を加えるようにします。 これが一番素直な解決方法かと。私はこちらで対応しています。
<a ng-href="#/search">Search</a>
を以下のように#/
を#!/
にしてあげます。
<a ng-href="#!/search">Search</a>
解決方法2
AngularJS 1.6 以前と同じく #/
でいけるようにするには、
$locationProvider.hashPrefix('')
を設定することで対応できます。
appModule.config(['$locationProvider', function($locationProvider) { $locationProvider.hashPrefix(''); }]);
参考
https://docs.angularjs.org/guide/migration#commit-aa077e8 https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52 http://stackoverflow.com/questions/41211875/angularjs-1-6-0-latest-now-routes-not-working http://stackoverflow.com/questions/41272314/angular-all-slashes-in-url-changed-to-2f
Gemに渡す町コードを一括保存するバッチを作成した
先日、以下の記事で紹介した、ごみ収集曜日を取得する処理をGemへ渡すためのコードを取得するバッチを作成しました。
なぜ作成したか。
先日書いた記事でも紹介しましたが、このGemでごみ収集曜日を取得するためには以下のパラメータとして以下のコードを渡す必要があります。
- 区コード
- 頭文字コード
- 町名コード
しかし、上記コードを見つけるためには、実際に横浜市のHPにアクセスし、URLを確認してパラメータを設定しなければなりません。 それだと、そもそも横浜市のHPにアクセスしているので「普通にで確認すれば良いじゃん」になるので、一括で上記コードを取得し、DBに保存するバッチを作成しました。
ページの構造
ごみ収集曜日のページ(横浜市資源循環局)は以下のような階層構造になっています。
収集曜日ページのトップです。区を選択することができます。 区の名前をクリックすると、その区の町名の頭文字を選択する画面に遷移します。
- 頭文字の選択ページ
例:港北区(区コード:16) http://cgi.city.yokohama.jp/shigen/kaishu/mobile/16
町(収集場所)の頭文字を選択する画面です。以下のような構成で各行ごとにリンクが貼られています。
[1] あ~お [2] か~こ [3] さ~そ [4] た~と [5] な~の [6] は~ほ [7] ま~も [8] やゆよ [9] ら~ろ、わ
- 町名の選択ページ
例:港北区(区コード:16) さ行(頭文字コード:3) http://cgi.city.yokohama.jp/shigen/kaishu/mobile/16/3
選択した区の選択した行(あかさたな)に該当する町名一覧が表示されます。
港北区のさ行では、以下の一覧が表示されます。
町名にリンクが貼られており、クリックすると、該当の町の収集曜日が表示されます。
篠原北1丁目 篠原北2丁目 篠原台町 篠原町 篠原西町 篠原東町1丁目 篠原東町2・3丁目 下田町1・2・3丁目 下田町4・5・6丁目 新横浜1・2・3丁目 新吉田町 新吉田東1~6丁目 新吉田東7・8丁目
- ごみ・資源物の収集日ページ
ここで、ごみ・資源物の収集日を確認することができます。
例:港北区(区コード:16) さ行(頭文字コード:3) 町コード 1073 http://cgi.city.yokohama.jp/shigen/kaishu/mobile/16/3/1073
Gemは、このURLを見てページからごみ収集曜日を取得します。
バッチの取得対象
先述した通り、
- 区コード
- 頭文字コード
- 町名コード
がわかれば、ごみ収集曜日を取得することができるので、 区から町名を選択する画面まで、リンクに含まれる各コードと名称を取得しながら再帰的にデータを取得していきます。
収集場所までバッチで持ってくれば良いのでは?とお思いの方もいらっしゃると思うのですが、 すべてのページのデータを持ってくるためには、 18区×あかたたな(9行)×町名分必要であり、横浜市のサーバへかなりのリクエストが発生してしまうため含めておりません。
あとは、もうGemつくちゃったしな・・・と、なんかすいません。といった感じです。
また、負荷については怒られないように、配慮していてバッチ内では5秒一回しかリクエストを飛ばさないようにしています。
作ってみた所感
今回は、基本となる機能は雑に一気に仕上げ、それから例外処理の追加やリファクタリングをしていくという流れで実装していきました。 ほぼ勢いで実装しましたが、丁寧に積み上げていく方式よりも自分の感覚的に合っているなと感じました。
というのは、処理を書く上で色々考えなければならないことがシンプルになるということ * Rubyっぽく書くには * クラスをどう分ける? * わかりやすい変数名は?
と、普段は実装する上で同時に考えることが多いので、まず一気に仕上げてから細かい部分を調整していくやり方にしてみて、こっちの方が性にあっているのでは?という気持ちになっていますす。(精神的にも疲れにくく、集中して取り組めたのではないかと感じました。)
すべてのケースには当てはまらないと思いますが、実装の仕方はこれからも試行錯誤しながらやっていきたいと思います。
ごみ収集曜日を取得する処理をGem化した
ごみ収集曜日を取得する処理だけを切り出し、Gem化したので、使い方をメモしておきます。
機能は随時更新していく予定です。
どのようなGemか?
横浜市資源循環局のページから、ごみ収集曜日の情報を取得しHashの配列で返します。
データ量の少ないモバイル版から取得しています。 http://cgi.city.yokohama.jp/shigen/kaishu/mobile/
使い方
例えば、港北区篠原町の収集曜日は以下のURLです。 http://cgi.city.yokohama.jp/shigen/kaishu/mobile/16/3/1073
区、頭文字、町名にそれぞれコードが振られており、上記URLの場合は、
- 区: 16
- 頭文字: 3
- 町名: 1073
になっています。
情報を取得するには、 Yokohama::Gomi::Schedule::App#fetch_schedule
メソッドを叩く必要があり、
引数にそれぞれ区、頭文字、町名、 ward_id:
,initial_code
,town_id
を指定します。
戻りは、取得した曜日(漢字)に対して、曜日に応じたごみの情報が入ったHashの配列(月〜土)で返ってきます。
作ってみて
Gemを作成するのは初めてでしたが、 bundle gem
コマンドを使うことで簡単に作成することができました。
現在は区、頭文字、町名のコードをがわかっていないと使えないので、今後は文字列から各コードを参照するような機能などを追加していきたいと思います。
DatabaseRewinderを追加した
【ごみ収集曜日APIシリーズ】FactoryGirlを追加した - takapi86のブログ
の続きです。
前回は、テストを2回目実行しようとすると、ユニーク制約に引っかかりエラーになってしまう問題が残ってしまいました。
今回はその対応として、DatabaseRewinder
というGemを使い、Rspecのテスト後に、
Createで作成したTestデータをデータベースから削除するようにしていきます。
上記のREADME.mdを参考にし導入しました。
導入
Gemfile
に database_rewinder
を追加して、bundle installします。
テスト環境のみで使用するので、 group
は test
だけでよいでしょう。
group :test do gem 'database_rewinder' end
rails_helper
に以下の記述を追加します。
複数DBを扱うわけではないので、基本的な設定でいきます。
RSpec.configure do |config| config.before(:suite) do DatabaseRewinder.clean_all end config.after(:each) do DatabaseRewinder.clean end end
試してみる
データがない状態で確認をしたいので、 以下のコマンドで、DBをリセットしておきます。
RAILS_ENV=test bundle exec rake db:migrate:reset
実行してみます。
bundle exec rspec spec/requests/towns_spec.rb .. Finished in 2.18 seconds (files took 3.28 seconds to load) 2 examples, 0 failures bundle exec rspec spec/requests/towns_spec.rb .. Finished in 1.43 seconds (files took 3.2 seconds to load) 2 examples, 0 failures
データを見てみます。
[1] pry(main)> Town.all Town Load (3.0ms) SELECT "towns".* FROM "towns" => [] [2] pry(main)>
2回以上実行しても、正常に動作し、テスト後のデータもすべてクリアされていました。
バッと書いてしまいましたが、今回はこんなところで。
FactoryGirlを追加した
いつもの、ごみシリーズです。
今週土日は、自分の所属しているバドミントンクラブのHPの作成で終わってしまいました。 デザイン難しい。
さて、今回は前回 RspecでHTTPのリクエスト・レスポンスのテストを行った - takapi86のブログ で追加したテストに、テストデータを追加していきます。
こちらを参考に導入を行いました。
File: GETTING_STARTED — Documentation for factory_girl (4.8.0)
導入
Gemfile
にfactory_girl_rails
を追加して、bundle install
します。
group :test do gem 'factory_girl_rails' end
- factory_girlのテストデータを作成するコードを保管する場所として、
spec/factories/
を作成しておきます。
ファイルを作成する
区モデル(ward)、町モデル(town)のFactoryGirlファイルを作成します。 ※ward、townは1:nの関係です。
詳しくは、
- spec/factories/wards.rbを作成
FactoryGirl.define do factory :ward do # モデル名を指定 sequence(:id) ward_code 16 name '港北区' end end
- spec/factories/towns.rbを作成
FactoryGirl.define do factory :town do # モデル名を指定 sequence(:id) ward_code 16 initial_code 3 town_code 1073 name '篠原町' end end
試してみる
- test環境にコンソールで入ります。
RAILS_ENV=test bundle exec rails c
wardのデータを作ってみる
[1] pry(main)> ward = FactoryGirl.create(:ward) (0.1ms) begin transaction SQL (0.4ms) INSERT INTO "wards" ("id", "ward_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["id", 1], ["ward_code", 16], ["name", "港北区"], ["created_at", 2017-03-26 14:57:30 UTC], ["updated_at", 2017-03-26 14:57:30 UTC]] (145.8ms) commit transaction => #<Ward:0x00559a99c3ccb8 id: 1, ward_code: 16, name: "港北区", created_at: Sun, 26 Mar 2017 14:57:30 UTC +00:00, updated_at: Sun, 26 Mar 2017 14:57:30 UTC +00:00>
townのデータを作ってみる
[2] pry(main)> FactoryGirl.create(:town, ward: ward) (0.1ms) begin transaction SQL (0.3ms) INSERT INTO "towns" ("id", "ward_code", "initial_code", "town_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["id", 1], ["ward_code", 2], ["initial_code", 3], ["town_code", 1073], ["name", "篠原町"], ["created_at", 2017-03-26 14:59:00 UTC], ["updated_at", 2017-03-26 14:59:00 UTC]] (60.9ms) commit transaction => #<Town:0x00559a9daa47f8 id: 1, ward_code: 2, initial_code: 3, town_code: 1073, name: "篠原町", created_at: Sun, 26 Mar 2017 14:59:00 UTC +00:00, updated_at: Sun, 26 Mar 2017 14:59:00 UTC +00:00>
うまくいったっぽいです。 念の為、testのDBはクリアしておきます。
RAILS_ENV=test bundle exec rake db:migrate:reset
前回のテストに追加
require 'rails_helper' RSpec.describe TownsController, type: :request, json: true do let(:town) { FactoryGirl.create(:town, ward: create(:ward)) } describe 'GET /towns/:name.json' do before do get URI.escape("/towns/#{town.name}.json") end it '200 OK を返す' do expect(response.status).to eq(200) end end end
こちらもうまくいったようです。
ちなみに、ここではFactoryGirl.create
と記載していますが、クラス名は、
spec_helper.rbの Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
のコメントを外し、以下のようにファイルを追加するか、そのままconfig.include FactoryGirl::Syntax::Methods
と追記することで、省略できます。
# spec/support/factory_girl.rb RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods end
ただ、このままでは2回目実行すると、以下のようなエラーが発生してしまうようです。
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: wards.id: INSERT INTO "wards" ("id", "ward_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) # ./spec/requests/towns_spec.rb:2:in `block (2 levels) in <top (required)>' # ./spec/requests/towns_spec.rb:7:in `block (3 levels) in <top (required)>' # ------------------ # --- Caused by: --- # SQLite3::ConstraintException: # UNIQUE constraint failed: wards.id # ./spec/requests/towns_spec.rb:2:in `block (2 levels) in <top (required)>'
どうやら、続けてテストする場合は、テスト後にテストしたデータを削除する処理を入れる必要があるようです。 こちらは、次回対応していきたいと思います。