継続的ブロギング

今度こそは続けるブログ

vimでプロジェクトファイル内テキスト検索(fzf)

f:id:akiza:20170806173906g:plain

こんな感じのやつです。

fzf.vimのREADMEに書いてあるやり方(↓)だと、開いたファイルと同階層のものしか見てくれなかったのでいろいろ試してみました。

github.com

自分の.vimrcに書いてあるfzfの設定はこんな感じです。

" fzf
set rtp+=/usr/local/opt/fzf

function! s:find_git_root()
  return system('git rev-parse --show-toplevel 2> /dev/null')[:-2]
endfunction

command! ProjectFiles execute 'Files' s:find_git_root()

command! -bang -nargs=* Pt
  \ call fzf#vim#grep(
  \   'pt --column --ignore=.git --global-gitignore '.shellescape(<q-args>), 1,
  \   <bang>0 ? fzf#vim#with_preview('up:60%')
  \           : fzf#vim#with_preview({ 'dir': s:find_git_root() }),
  \   <bang>0)

最後のPtというところがそうです。
ほぼREADMEに書いてあるのと一緒ですが、ポイントは { 'dir': s:find_git_root() } をオプションに渡していることです。
あと、自分は検索ツールにthe_platinum_searcherを使っているので、そこは変えています。

github.com

とりあえずご参考まで。。

fzfもっと使いこなしたい!

実践Vim 思考のスピードで編集しよう! (アスキー書籍)

実践Vim 思考のスピードで編集しよう! (アスキー書籍)

CircleCI2.0に移行しました(Rails)

早くなるという噂を聞いたので試しにやってみたら、少しだけ早くなりました。(8min→6min)

.circleci/config.yml

version: 2
jobs:
  build:
    docker:
      - image: ruby
        environment:
          - TZ: "/usr/share/zoneinfo/Asia/Tokyo"
          - LANG: ja_JP.UTF-8
          - LC_ALL: C.UTF-8
          - LANGUAGE: ja_JP.UTF-8
      - image: circleci/mysql
        environment:
          - MYSQL_ROOT_PASSWORD:

    # parallelism: 2
    working_directory: ~/repo
    steps:
      - checkout

      # Restore cache
      - type: cache-restore
        key: phantomjs-2.1.1
      - type: cache-restore
        key: repo-{{ checksum "Gemfile.lock" }}

      - run: apt-get update

      # Install phantomjs
      - run: apt-get install -y fonts-migmix
      - run: |
          which phantomjs && exit
          curl --location --silent https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 | tar xj -C /tmp --strip-components=1
          mv /tmp/bin/phantomjs /usr/local/bin/phantomjs

      # Bundle install dependencies
      - run: bundle install -j 4 --path vendor/bundle

      # Store cache
      - type: cache-save
        key: phantomjs-2.1.1
        paths:
          - /usr/local/bin/phantomjs
      - type: cache-save
        key: repo-{{ checksum "Gemfile.lock" }}
        paths:
          - vendor/bundle

      # DB setup
      - run: bundle exec rake db:create
      - run: bundle exec ridgepole -E test -c config/database.yml --apply -f db/Schemafile --enable-migration-comments

      # Run rspec in parallel
      - type: shell
        command: |
          bundle exec rspec --profile 10 \
                            --format RspecJunitFormatter \
                            --out /tmp/test-results/rspec.xml \
                            --format progress \
                            $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)

      - run: bundle exec rubocop -D -R -c .rubocop.yml

      - type: store_artifacts
        path: tmp/capybara/
        destination: capybara

      # Save artifacts
      - type: store_test_results
        path: /tmp/test-results

基本的には公式のものを参考に作りましたが、気をつけた点を少し紹介させていただきます。

Language Guide: Ruby - CircleCIcircleci.com

rubyはcircleci/rubyを使わず、docker公式のものを採用

https://hub.docker.com/r/circleci/ruby/

CircleCIが用意してくれているDockerイメージがあって、gitsshやDockerツールが最初からインストールされていてと便利なのですが、phantomjsインストールして使用する際に少し面倒だったので、公式のものを使うようにしました。

mysqlの方はcircleci/mysqlを使っています。

https://hub.docker.com/r/circleci/mysql/

phantomjsのインストール

個人 Rails アプリを CircleCI 2.0 で動くようにした - アジャイルSEの憂鬱sinsoku.hatenablog.com

こちらのブログを参考にさせていただきました。
ありがとうございました。

ArgumentError: invalid byte sequence in US-ASCIIが出る対策

ArgumentError: invalid byte sequence in US-ASCII on v2.2.0 in Docker · Issue #277 · ffaker/ffaker · GitHubgithub.com

上記URLを参考に下記設定をしています。

environment:
  - LANG: ja_JP.UTF-8
  - LC_ALL: C.UTF-8
  - LANGUAGE: ja_JP.UTF-8

featureスペックエラー時に保存しているスクリーンショットを見れるように

- type: store_artifacts
  path: tmp/capybara/
  destination: capybara

tmp/capybaraに保存したスクリーンショットをCircleCIのArtifactsから見れるようにしています。

f:id:akiza:20170702115849p:plain

まとめ

CIが少しでも早くなることは嬉しいですね。
まだβ版ですが使って見る価値はあるのではないでしょうか。

クローラー(スクレイピング)をRspecでテスト

今回初めて、個人用にクローラーを開発してみました。
JavaScript多めのサイトのため、「Capybara + Poltergeist」を使用しました。

順調に開発は進んだのですが、テストってどう書けばいいんだろうと思い、知り合いに相談したところ、下記方針に決まりました。

  • feature_specとして書く
  • 毎回アクセスするのはよろしくないので、用意したHTMLファイルを解析する

やり方

CapybaraのHTTPリクエストをstub化する

毎回アクセスしないように、CapybaraのHTTPリクエストをstub化し、用意したローカルのHTMLファイルを返却するようにします。

HTTPリクエストをスタブ化するGemとして「webmock」は有名だと思います。

github.com

しかし、これはCapybaraでは使えません。
代わりに「puffing-billy」を使います。

github.com

Gemをインストールして、設定を追加します。
README通りだと、jsのエラーが無視されずRspecが失敗してしまうため、私は以下のように設定しました。

Capybara.register_driver :pg_billy do |app|
  options = {
    js_errors: false,
    phantomjs_options: [
      '--ignore-ssl-errors=yes',
      "--proxy=#{Billy.proxy.host}:#{Billy.proxy.port}"
    ]
  }
  Capybara::Poltergeist::Driver.new(app, options)
end
Capybara.configure do |config|
  config.default_driver = :pg_billy
  config.javascript_driver = :pg_billy
end

テストを書いてみる

テストコードはこんな感じです。

require 'rails_helper'

feature 'Login' do
  background do
    Billy.config.record_stub_requests = true
  end

  given(:url) { "http://www.example.com" }
  
  scenario 'login' do
    proxy.stub(url).and_return(body: File.read("spec/features/htmls/login.html"))
    visit url

    within("#form") do
      fill_in 'id', with: 'id'
      fill_in 'password', with: 'password'
    end

    stub = proxy.stub(url, method: 'post').and_return(
      headers: { 'Access-Control-Allow-Origin' => '*' },
      code: 200,
      text: "Success"
    )
    click_button('ログイン')

    request_params = stub.requests.shift[:body].split("&")
    expect(page).to have_content("Success")
    expect(request_params).to include("id=id", "password=password")
  end
end

ポイント1

Billy.config.record_stub_requests = true

フィールドに値が入って、ちゃんとPostされているかチェックするため、リクエスト情報を記録するようにしています。

ポイント2

proxy.stub(url).and_return(body: File.read("spec/features/htmls/login.html"))

指定のURLにアクセスした際に、用意したHTMLをbodyに入れて返すようにしています。

ポイント3

stub = proxy.stub(url, method: 'post').and_return(
      headers: { 'Access-Control-Allow-Origin' => '*' },
      code: 200,
      text: "Success"
    )

ログイン処理をstub化しています。

最後に、フィールドに値がちゃんと入っていること、ログインボタンが押されたことをチェックして、テストは完了です。

なかなか情報もなく、いろいろ悩んだ末、今回このようにテストしてみました。
「うちはこうやってるよ」とかアドバイスいただけるとありがたいです!

参考

Rubyでやるならこの本はオススメです!

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

メール受信 → 解析(Postfix + Rails)

Railsアプリと連携して下記のことをしたい。

  1. メール受信でRailsアプリ内プログラム実行
  2. メールの中身を確認

今回はMacのローカル環境で検証します。

環境

手順

まずはメール受信できるように

1. Postfixの起動(元々入っている)

$ sudo postfix start

2.メール送信

$ mail <Macユーザー名>

件名入力 → 本文入力 → 最後にEnterで改行して、'.'を入力してEnter

3.メール確認

$ mail

メールを受信することができました!

メール受信→プログラム実行してみる

1.プログラム作成

  • mailin
$ vim /Users/fakiyer/rails_project/script/mailin
#! /usr/bin/env bash
cd /Users/fakiyer/rails_project
/Users/fakiyer/.rbenv/shims/rails runner -e development ‘Mailer.receive(STDIN.read)'
$ chmod 777 /Users/fakiyer/rails_project/script/mailin
  • Mailer
def self.receive(mail)
  email = Mail.new(mail)
  body = email.body.decoded
  charset = email.charset
  body = body.force_encoding(charset).encode('utf-8')

  logger.info body
end

2.Postfixのaliases設定

$ sudo vim /etc/aliases
...
  <Macユーザー名>
  fakiyer: "| /Users/fakiyer/rails_project/script/mailin”
$ sudo newaliases

3.Postfix実行ユーザー変更

  • main.cf
#default_privs = nobody
default_privs = fakiyer
$ sudo postfix start

4.メール送信

$ mail <Macユーザー名>

railsログにbodyの内容が出力されているはずです!

参考

New RelicでDockerコンテナ監視 - Elastic Beanstalk

現在Elastic BeanstalkのMulti-Container Docker環境を使っています。

New Relicを使ってコンテナを監視するようにしたので設定をメモ。
公式のドキュメントがだいぶ丁寧なので、ほとんどその通りなのですが。。。

設定ファイルを追加するだけ

  • .ebextensions/newrelic.config
packages:
  yum:
    newrelic-sysmond: []
  rpm:
    newrelic: http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm
commands:
  "01":
    command: usermod -a -G docker newrelic
  "02":
    command: nrsysmond-config --set license_key=YourNewRelicLicense 
  "03":
    command: echo hostname=NameOfYourServer >> /etc/newrelic/nrsysmond.cfg
  "04":
    command: /etc/init.d/newrelic-sysmond start

あとは.ebextensionsとDockerrun.aws.jsonをzipにしてdeployするだけです!

参考

DockerでWhenever(gem)が動かなくてハマった話

久々の更新です。
最低でも月1で書きたいなあと思ってたのですが、2ヶ月以上も空いてしまいました。
最近はRailsはもちろんのこと、React NativeやDockerもバリバリ使ってます!

さて、標題の件ですが、いやー、かなりハマりました。

現在、開発環境にDocker(Docker Compose)を使って、Railsアプリを開発しています。
そして、crontab管理にwheneverというgemを使っています。

コンテナでcronを動かしたいなと思ったのですが、なかなかうまくいかない。。。
cronをインストールして、起動して、wheneverのコマンドでcrontabの設定も完了したのですが、実行時間になるとwheneverのログにエラーが。

Could not find rake-10.5.0 in any of the sources (Bundler::GemNotFound)

crontabに設定されているコマンドをdocker-compose run等で実行すると正常に実行される。

いろいろ調べて下記サイトに辿り付きました。

support.aptible.com

qiita.com

環境変数を渡してあげなきゃいけないみたいです。

一番目のリンクの通り、config/schedule.rbにENV.each { |k, v| env(k, v) }を追記したらうまくいきました。

ghq + peco!じゃなくて fzf連携

対象

ghq + fzf

よく ghq + peco でやってる記事が挙がってますが、それのfzf 版です。
ghq で管理しているリポジトリのパスをインクリメンタルサーチして、選択すると、cdするスクリプトです。

frepo() {
  local dir
  dir=$(ghq list > /dev/null | fzf-tmux --reverse +m) &&
    cd $(ghq root)/$dir
}

f:id:akiza:20160129142308g:plain

私も最近 fzf 使い始めたばかりなので、fzf 使いの方、良い情報あったら教えてください!

最後に

おい、peco もいいけど fzf 使えよ - Qiita

この記事を見てから、fzfを使うようになりました。
素晴らしい記事をありがとうございました!