正規表現で名前付きキャプチャが便利だった

これがあれば何にマッチさせているかわかるじゃん!って感動しました。

正規表現でキャプチャするときに$1で変数格納されますが、この場合何にマッチさせているのかがわかりづらいときがあります。 何より量が増えてくるとしんどいです。

使い方

(?<name>正規表現を書いてください)

サンプルです。

text =  ["塚本連平(MMJ)", "小松隆志(MMJ)", "六車俊治(テレビ朝日)"]
text.split(/\s/).map do |director|
  m = director.match(/(?<name>.*)(?<organization>.*)/)
  {
    name: m[:name],
    organization: m[:organization]
  }
end

=> [{:name=>"塚本連平", :organization=>"(MMJ)"}, {:name=>"小松隆志", :organization=>"(MMJ)"}, {:name=>"六車俊治", :organization=>"(テレビ朝日)"}]

何をやっているのかがわかりやすいです。

$1 よりも圧倒的にやりやすい。

今後とも使っていきます。

rubyでeach_index_withでindexの値を0以外から始める方法

rubyでeach x indexをしたいパターンが多いです。

そのために、each_with_indexというメソッドがあります。

each_with_index

こちらは基本的に初期値が0からになります。

array = %w(foo bar baz)
array.each_with_index do |x, index|
  puts "#{index}番目#{x}"
end

=>
0番目foo
1番目bar
2番目baz

1から始めたいという場合は、下記のようにすることで回避できます。

array = %w(foo bar baz)
array.each_with_index do |x, index|
  puts "#{index + 1}番目#{x}"
end

=>
1番目foo
2番目bar
3番目baz

ただ、いちいち+ nを書かないといけないので、めんどくさいです。

each.with_index

そこで、each.with_indexを使用します。

こちらは()を入れることで開始位置を指定できます。

array = %w(foo bar baz)
array.each.with_index(1) do |x, index|
  puts "#{index}番目#{x}"
end
=>
1番目foo
2番目bar
3番目baz

まとめ

indexを0から始める場合は、each_with_index 0以外から始める場合は、each.with_index(n)をするのがいいのかなと個人的には思いました。

ActiveModelでcallbackをする方法

Formオブジェクトを使用していて、まともにActiveModelを使用しました。

ActiveRecordの場合は自動的にcallbackを仕込めるのですが、ActiveModelの場合はどうすればいいのかわからなかったです。

使い方

class WorkForm
  include ActiveModel::Model
  define_model_callbacks :save←callbackを定義する

  before_save :valid_resource←callbackのメソッドを作成する

  def save
    run_callbacks :save do←使用する場所を書く
    ...
    end
  end


  private

  def valid_resource
     ...←処理を書く
  end
end

公式に書いてあります。

ActiveModel::Callbacks

以上です。

rails5でautoload問題を解決する

やられましたよ。

rails4 → rails5へのアップデートをしていたのですが、libpathの配下のものが読まれない。

config/application.rb

    config.autoload_paths += %W(#{config.root}/lib)

問題ないだろ。

そう思っていましたよ。

どうやら、この作業が無効になっています。

2.6 production 環境での起動後は自動読み込みが無効になる 今後Railsがproduction 環境で起動されると、自動読み込みがデフォルトで無効になります。

アプリケーションの一括読み込み(eager loading)は起動プロセスに含まれています。このため、トップレベルの定数についてはファイルをrequireしなくても問題なく利用でき、従来と同様に自動読み込みされます。

トップレベルより下で、実行時にのみ有効にする定数(通常のメソッド本体など)を定義した場合も、起動時に一括読み込みされるので問題なく利用できます。

ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。めったにないと思われますが、productionモードで動作するアプリケーションで自動読み込みが必要な場合は、Rails.application.config.enable_dependency_loadingをtrueに設定してください。

Rails アップグレードガイド | Rails ガイド

ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。

いや、だいぶ影響あるだろ。

みんな使ってますよ!

ということで解決策

config.enable_dependency_loading = true

これはアップグレードガイドに書いていますね。

他にもやり方があります。

参考

qiita.com

危ない危ない・・・。

nodeのメモリー足らない問題をswapで回避する

AWSのt2.microだと、メモリーが1Gです。

webpackerを使用していると、普通にdeployで落ちてしまいます。

FATAL ERROR: JS Allocation failed - process out of memory
Aborted

こんな感じのエラーが出てにっちもさっちもいかなかったです。

memoryが足らないと言うことで、memoryを増やせばいいのですが、無料期間なので、グレードをあげて対処するなんてもったいないです。

どうしよう・・・っと思っていたところに、swap領域を作れば回避できるんじゃないですか?とアドバイスをいただいたので、swap領域を作成することにした。

AWSの上位インスタンスだと、最初からswapはあるようだけど、安いインスタンスだとなかった。

あと、inuxだと、swap領域を自分で設定できたとは知らなかった。

swapとは

HDDにメモリー領域を作成して、高速にアクセスできるようにします。 パソコンはメモリー上にある領域は高速にアクセスできるのですが、HDDに書き込みするのは遅いです。 ということで、memoryが足らない状態になると、HDDにメモリー領域を作成します。

今回は実際のメモリー上のアクセスしかしていなくて、メモリー領域が足らなくて落ちていました。

コマンド

sudo dd if=/dev/zero of=/swap bs=1M count=1024
sudo mkswap /swap
sudo swapon /swap

んで、freeコマンドで確認する。

Mem:       1022936     831780     191156       1592      80336     183480
-/+ buffers/cache:     567964     454972
Swap:      1048572      10064    1038508

無事にできている。

topコマンドでもきちんと作成されています。

top - 21:06:59 up 1 day, 21:51,  1 user,  load average: 0.00, 0.05, 0.14
Tasks:  64 total,   1 running,  63 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.1 sy,  0.0 ni, 98.3 id,  0.9 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   1022936 total,   832076 used,   190860 free,    80336 buffers
KiB Swap:  1048572 total,    10064 used,  1038508 free.   183504 cached Mem

きちんとコンピューターの仕組みがわかれば大した問題じゃないのですが、解決できてよかった。

意外にサーバー面白い!

gitのリポジトリの中で、issueのURLを開くコマンドを作成した

いちいちgitを開けるのが面倒くさいってパターンです。

#!/usr/bin/env ruby

require 'open-uri'

url = "https://github.com/foo/bar/issues/#{ARGV.first}"

system "open #{url}"

ファイル名をbin/issueで登録する。

bin/issue 10

これで開きます。

もう少しいい書き方がありそう。

面倒くさいので、ターミナルからブラウザを開く行動までやっていきたいですね。

rubyでrakeの外部コマンドが失敗した時のエラーハンドリング

webpackerを使用していて、webpacker installって出ているのに、installは失敗していた。

これはムカつくからpullreq出してやろうと思ったら、すでにあった。

さすがだ。

fail hard when webpacker:install ./bin/yarn fails by sealocal · Pull Request #149 · rails/webpacker · GitHub

んで、実際のエラーハンドリング方法が思いつかなったので、これは参考になりました。

run './bin/yarn add webpack webpack-merge path-complete-extname babel-loader babel-core babel-preset-env coffee-loader coffee-script compression-webpack-plugin rails-erb-loader glob'
unless $?.success?
  puts set_color 'Failed to install webpack!', :red
  exit $?.exitstatus
end

$?はprocessの実行結果がいます。

これを見て、成功したかどうかを判定して、エラー内容を記述していました。

芸がこまかい。

そして、$?自体初めて知りました。

スレッドで最後の実行結果が入っているのですね。

$?自体がUNIXの実行結果の可否を調べるものなので、それと同じ動きをしていたってことですね。

% cat foo
=>cat: foo: No such file or directory

% echo $?
=>1

この辺はUNIX/Linux使いで、シェルとか作ってる人は分かるのでしょうが、自分は使ってないので、思いつかなかったので、これをきっかけに覚えておく。

variable $? (Ruby 2.4.0)

以上です。

nvmでnodeをインストールしているのに、deployしたら「/usr/bin/env: node: No such file or directory」が出る場合

なんでだよ!

node -v
=> v7.7.4

deploy→/usr/bin/env: node: No such file or directory

確実にインストールはされている。

ということで、シンボリックリンクを貼りましょう。

sudo ln -s "$(which node)" /usr/bin/node

ちなみにdebianのversion

cat /etc/debian_version
→8.3

これより古いと、別のパターンもあるので、、適切なものを選びましょう。

【Node.js】【PM2】 PM2でさくらVPSにNode.jsのアプリケーションをデプロイ - 人生dat落ち

rails5からはcontrollerテスト書くぐらいなら、requestテストを書くのがいいっぽい

controllerテストいらねみたいな流れだったけど、requestテスト書けって話だったのか。

Rails 3 と 4 において、controller spec の assigns は慣用されてきました。 今回の RSpec 3.5 はマイナーリリースであり、私たちは SemVer に準拠する以上、 既存の controller spec を壊さないようにしています。 既存の Rails アプリケーションで assigns を多用しているものについては、 rails-controller-testing gem を Gemfile に追加することで assigns と assert_template を復活させることができます。 RSpec はこの gem とシームレスに連携するため、controller spec は問題なく動作し続けるはずです。

これから新しく作成する Rails アプリケーションについては、 rails-controller-testing gem を追加するのはおすすめしません。 Rails チームや RSpec コアチームとしては、代わりに request spec を書くことを推奨します。 Request spec は一つのコントローラーアクションにフォーカスしますが、 controller spec とは違い、ルーターミドルウェアスタック、Rack リクエストやレスポンスも関与します。 これによって、より現実に近い環境でテストを実行し、controller spec で発生しがちな多くの問題を避けることができます。

RSpec 3.5 がリリースされました!

今までもassingsを使用していたcontrolelrテストだと、下記を入れれば今まで通り使用できます。

GitHub - rails/rails-controller-testing: Brings back `assigns` and `assert_template` to your Rails tests

これを使うぐらいなら、requestテストを書けって流れみたいだ。

なお、requestテストはcontrollerテストよりも早くなっているらしいので、早速試した。

Rails 5 では、request spec が Rails 4までの request spec や controller spec よりもかなり高速になっています。 これは Rails チームの Eileen Uchitelle1 のおかげです。

rails5のrequest

Finished in 0.33271 seconds (files took 5.43 seconds to load)
1 example, 0 failures

controller

Finished in 0.277 seconds (files took 11 seconds to load)
1 example, 0 failures

controllerの方がまだ早いかな・・・

流れ的には、requestテストの方がリアルなデータが取れるので、そっちを使えってことなので、今後はrequestテストを書いていく。

rails5ではrender methodをいたるところで使えるようになっている

rails5にアップデートするときに変更されていて、手を加えて変更したので、備忘録として書いておきます。

rails4.2時代のrenderのやり方

下記のように、requestを強引に擬似るような形でやっていました。

class Renderer
  def renderer
    controller = ApplicationController.new
    controller.request = ActionDispatch::TestRequest.new
    ViewRenderer.new(Rails.root.join('app', 'views'), {}, controller)
  end
end

class ViewRenderer < ActionView::Base
  include Rails.application.routes.url_helpers
  include ApplicationHelper

  def default_url_options
    { host: Rails.application.routes.default_url_options[:host] }
  end
end

Renderer.new.render

こういうやり方ではなく、ActionController::Rendererというクラスメソッドが作られました。

コントローラのアクションの外部で任意のテンプレートでレンダリングするActionController::Rendererを追加。 (Pull Request)

rails/rendering.rb at master · rails/rails · GitHub

ということで、下記のようにすることでrenderをいたるところで呼べるようになりました。

ApplicationController.renderer.render partial: 'topics/image', locals: { url: url, host_name: host_name }

以上です。