Rubyと筋肉とギターとわたし

エンジニア二年目の雑魚です。プログラミング・ギター・筋トレのことをメインにブログを書いていきます。

【GCE】SendgridをGCPのlauncherで連携せずに使う

f:id:rdwbocungelt5:20180727094804j:plain

どうもてぃです。

今回は自分でアカウント登録したSendgridとGCEを連携させてメールを送信したいと思います。

準備

今回はGCP上のMarketplace検索すると使えるLauncherであるSendgridではなく、自分で登録したものを使います。

以下、リンク。

sendgrid.com

googleで検索すると上位には日本版Sendgridが出てきますが、これは使わないように。

というよりも、審査があってすぐには使えないのでとても不便。登録すると一瞬で使える本家(https://sendgrid.com)を使いましょう。

ここで、作成したAPIキーやら、usernameやらパスワードをしっかりメモっておくこと。

はまった

準備ができたら、公式に書いてある通りの順序でやっていきました。

cloud.google.com

僕はSendgridのAPIキーを取得して、それを/etc/postfix/sasl_passwdに設置しました。

Railsの本番環境を作っていてどうせAPIキーを使う予定だったので。

mailxでメール送信

設定を終えて、問題ないかmailxを使ってメール送信してみました。

# echo 'テストメールです' | mail -s 'テストめーる' mailaddress@gmail.com
# send-mail: 550 Unauthenticated senders not allowed

何故か送れない。

maillogも確認してみる。

# tail /var/log/maillog

Jan 21 05:09:09 instance-1 postfix/master[11145]: daemon started -- version 2.10.1, configuration /etc/postfix
Jan 21 05:09:40 instance-1 sSMTP[11153]: 550 Unauthenticated senders not allowed

ssmtpでの550が出てる。

対処法

Sendgrid公式に書いてありました。

今回は、GCPで予め用意されているものを使わず、自分で一から設定したので発生したのかも。

前やった時はGCPのSendgrid公式ドキュメントだけで問題なくいけたから。

sendgrid.com

ここで、/etc/ssmtp/ssmtp.confを設定すればおk。

ただし、今回はGCPなのでmailhub=smtp.sendgrid.net:587のポートを2525に変えてあげる。

正しくはmailhub=smtp.sendgrid.net:2525です。

解決!

いろいろ記事とか検索したけど、やっぱり公式ドキュメントを見るのが一番早いですね。

コマンドでメール送れたので、今度はRails側からも送ってみたいと思います。

ではでは。

【Rails】unicornの謎エラー

どうもてぃです。

unicornの設定でかなり手間取りました。

環境

起きたこと

とある記事を参考にunicornを設定し、ローカルでbundle exec rails unicorn:startしたところ以下のエラーでハマりました。

I, [2019-01-15T16:48:10.401826 #1790]  INFO -- : Refreshing Gem list
I, [2019-01-15T16:48:11.349098 #1790]  INFO -- : unlinking existing socket=/home/user/project/tmp/unicorn.sock
I, [2019-01-15T16:48:11.349216 #1790]  INFO -- : listening on addr=/home/user/project/tmp/unicorn.sock fd=14
E, [2019-01-15T16:48:11.349315 #1790] ERROR -- : unsupported signal SIGTEAM (ArgumentError)
/home/user/project/config/unicorn.rb:11:in `trap'
/home/user/project/config/unicorn.rb:11:in `block in reload'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:543:in `spawn_missing_workers'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:142:in `start'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/bin/unicorn:126:in `<top (required)>'
/home/user/project/vendor/bundle/ruby/2.5.0/bin/unicorn:23:in `load'
/home/user/project/vendor/bundle/ruby/2.5.0/bin/unicorn:23:in `<main>'

おそらく ERROR -- : unsupported signal SIGTEAM (ArgumentError)これが原因かと。

ローカル環境でやったのがまずかったのかなと思い、GCEのCentOS7上で環境を作ってやってみたのですが、同じエラーが出ました。

やったこと

最初もいいましたが、まず、以下の記事を参考にファイルを作成し設定をしていきました。

qiita.com

bundle exec rails unicorn:startで作成したタスクを実行したのですが、上記のエラー。

そして、どれだけ探しても同じエラーで詰んでる人がいないという。

と思っていたところ、以下の記事が出てきた。

doruby.jp

記事を参考にconfig/unicorn.rbを変更してみました。

#  unicron.rb
# set lets
$worker  = 2
$timeout = 30
$app_dir = "/home/user/project/" #アプリの場所
$listen  = File.expand_path 'tmp/unicorn.sock', $app_dir
$pid     = File.expand_path 'tmp/unicorn.pid', $app_dir
$std_log = File.expand_path 'log/unicorn.log', $app_dir

# set config
worker_processes  $worker
working_directory $app_dir
stderr_path $std_log
stdout_path $std_log
timeout $timeout
listen  $listen
pid $pid

# loading booster
preload_app true

# before starting processes
before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
  old_pid = "#{server.config[:pid]}.oldbin"

  if old_pid != server.pid
    begin
      Process.kill "QUIT", File.read(old_pid).to_i
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

# after finishing processes
after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

これで一旦はbundle exec rails unicorn:startが動くようになりました。

終わりに

今回の解決策には全くなってないですが、プロジェクトの関係で早く本番環境を作らないといけないので、一旦この方法で落ち着けます。

時間のあるときにもうすこし調査してみます。

誰か解決してくれるといいんだけど。

【Ubuntu】apt update時winehqでGPGエラー

f:id:rdwbocungelt5:20190116114707p:plain

どうもてぃです。

apt-keyの更新とか設定とかメンドイですね。今回身をもって知りました。

環境

  • Ubuntu 16.04.5 LTS(elementary OS 0.4.1 Loki)

現象

$ sudo apt update

無視:1 http://dl.google.com/linux/chrome/deb stable InRelease
ヒット:2 http://dl.google.com/linux/chrome/deb stable Release                                                                                             
ヒット:3 https://dl.yarnpkg.com/debian stable InRelease                                                                                                   
ヒット:4 https://download.docker.com/linux/ubuntu zesty InRelease                                                    
ヒット:5 https://cli-assets.heroku.com/apt ./ InRelease                                                              
ヒット:8 http://packages.elementary.io/appcenter xenial InRelease                                                      
ヒット:9 http://ppa.launchpad.net/elementary-os/stable/ubuntu xenial InRelease                                         
エラー:7 https://dl.winehq.org/wine-builds/ubuntu xenial InRelease                                                     
  公開鍵を利用できないため、以下の署名は検証できませんでした: NO_PUBKEY 76F1A20FF987672F
ヒット:10 http://archive.ubuntu.com/ubuntu xenial InRelease                                                            
ヒット:11 http://ppa.launchpad.net/gregory-hainaut/pcsx2.official.ppa/ubuntu xenial InRelease
ヒット:12 http://archive.ubuntu.com/ubuntu xenial-updates InRelease                                                     
ヒット:13 http://archive.ubuntu.com/ubuntu xenial-backports InRelease                                                  
ヒット:14 http://ppa.launchpad.net/noobslab/pcsx2/ubuntu xenial InRelease                   
ヒット:15 https://packagecloud.io/slacktechnologies/slack/debian jessie InRelease                                       
ヒット:16 http://archive.ubuntu.com/ubuntu xenial-security InRelease                                                    
ヒット:17 http://ppa.launchpad.net/elementary-os/os-patches/ubuntu xenial InRelease                                     
ヒット:18 http://ppa.launchpad.net/philip.scott/elementary-tweaks/ubuntu xenial InRelease 
ヒット:19 http://ppa.launchpad.net/ubuntuhandbook1/audacity/ubuntu xenial InRelease       
ヒット:20 http://ppa.launchpad.net/webupd8team/java/ubuntu xenial InRelease               
パッケージリストを読み込んでいます... 完了                    
W: GPG エラー: https://dl.winehq.org/wine-builds/ubuntu xenial InRelease: 公開鍵を利用できないため、以下の署名は検証できませんでした: NO_PUBKEY 76F1A20FF987672F
E: リポジトリ https://dl.winehq.org/wine-builds/ubuntu xenial InRelease は署名されていません。
N: このようなリポジトリから更新を安全に行うことができないので、デフォルトでは更新が無効になっています。
N: リポジトリの作成とユーザ設定の詳細は、apt-secure(8) man ページを参照してください。

winehqで公開鍵がないんかな、と予想。

やったこと

まずはwikiを参照。

wiki.winehq.org

そしたらtopに書いてありました。

$ wget -nc https://dl.winehq.org/wine-builds/winehq.key

$ sudo apt-key add winehq.key

$ sudo apt update

これだけだったなんて。

終わりに

しばらくエラーが出てて更新できてなかったので、その後apt upgradeやりました。

やはり一時情報を確認するのが大切ですね。

めでたしめでたし。

【Ubuntu】apt updateで404 not found

f:id:rdwbocungelt5:20190116114707p:plain

どうもてぃです。

いろいろ環境構築してる時にタイトルの子が出てくるとかなり困る。

なんとか解決してみました(解決できたかどうか微妙だが)。

環境

  • Ubuntu 16.04.5 LTS(elementary OS 0.4.1 Loki)

やったこと

いろんな記事を試しました。

が、メインは以下の記事の手順。

qiita.com

今回公開鍵のエラーも出てたので以下も参考にした。

www.trifields.jp

公開鍵エラーの方はなんとか直ったんですが、404 not foundエラーの方が直らない。

リポジトリはこの子。

エラー:44 http://ppa.launchpad.net/hunter-kaller/ppa/ubuntu xenial Release
  404  Not Found

E: リポジトリ http://ppa.launchpad.net/hunter-kaller/ppa/ubuntu xenial Release には Release ファイルがありません。
N: このようなリポジトリから更新を安全に行うことができないので、デフォルトでは更新が無効になっています。
N: リポジトリの作成とユーザ設定の詳細は、apt-secure(8) man ページを参照してください。

なので一旦リポジトリを取り直してやってみたが、、、

$ sudo add-apt-repository ppa:hunter-kaller/ppa

$ sudo apt -y update


・
・
・
・
・
・
・
エラー:44 http://ppa.launchpad.net/hunter-kaller/ppa/ubuntu xenial Release
  404  Not Found

E: リポジトリ http://ppa.launchpad.net/hunter-kaller/ppa/ubuntu xenial Release には Release ファイルがありません。
N: このようなリポジトリから更新を安全に行うことができないので、デフォルトでは更新が無効になっています。
N: リポジトリの作成とユーザ設定の詳細は、apt-secure(8) man ページを参照してください。

だめだなこれは。

対処法

Releaseファイルがないということはリポジトリの更新がそもそも止まってるんじゃね?と思い、なら必要ないんじゃないかという結論に至ったので消しました。

/etx/apt/sources.list.d/配下にhunter-kaller-ubuntu-ppa-xenial.listがいるので、削除してしまう。

けど、もしエラーになったら面倒なので、一応バックアップとして取っておく方法にする。

$ sudo mkdir /etc/apt/backup

$ sudo mv /etc/apt/sources.list.d/hunter-kaller-ubuntu-ppa-xenial.* /etc/apt/backup/

$ sudo rm -rf /var/lib/apt/lists/*

$ sudo apt update

これで一旦問題なくupdateできました。

【Rails】unicorn.rbでRails.rootが使えない

どうもてぃです。

本番環境を作ってます。環境ってすごく大事ですよね。

今回何も考えずデフォルトのサーバーpumaを使っていたので、unicornに移行しようと設定していたところ起きた問題です。

環境

起きたこと

worker_processes Integer(ENV['WEB_CONCURRENCY'] || 3)
timeout 15
preload_app true

listen Rails.root.join('tmp', 'unicorn.sock')
pid    Rails.root.join('tmp', 'unicorn.pid')

before_fork do |server, worker|
  Signal.trap 'TEAM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill('QUIT', Process.pid)
  end

  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothind. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

stderr_path File.expand_path('log/unicorn.log', Rails.root)
stdout_path File.expand_path('log/unicorn.log', Rails.root)

上記がunicornの設定ファイルです。

これを元にサーバー起動をしてみたところ、以下のエラーが発生。

# lib/tasks/unicorn.rake を実行する
$ bundle exec rails unicorn:start

unicorn -c /home/user/project/config/unicorn.rb -E development -D
Traceback (most recent call last):
    9: from /home/user/project/vendor/bundle/ruby/2.5.0/bin/unicorn:23:in `<main>'
    8: from /home/user/project/vendor/bundle/ruby/2.5.0/bin/unicorn:23:in `load'
    7: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/bin/unicorn:126:in `<top (required)>'
    6: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/bin/unicorn:126:in `new'
    5: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:77:in `initialize'
    4: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:77:in `new'
    3: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/configurator.rb:77:in `initialize'
    2: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/configurator.rb:84:in `reload'
    1: from /home/user/project/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/configurator.rb:84:in `instance_eval'
/home/user/project/config/unicorn.rb:5:in `reload': uninitialized constant #<Class:#<Unicorn::Configurator:0x000055a569137798>>::Rails (NameError)
master failed to start, check stderr log for details
rails aborted!
Command failed with status (1): [unicorn -c /home/user/projec...]
/home/user/project/lib/tasks/unicorn.rake:5:in `block (2 levels) in <main>'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/command.rb:48:in `invoke'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/commands.rb:18:in `<main>'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in `register'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/dependencies.rb:287:in `block in require'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/dependencies.rb:253:in `load_dependency'
/home/user/project/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/dependencies.rb:287:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => unicorn:start
(See full trace by running task with --trace)

たいていどこのファイルでも問題なくRailsを使えるので何も疑ってなかったのですが、色々調べたところ使えないようです。

やったこと

require 'rails'をやってみたんですが、Rails.rootnilで返ってくる。

故に、joinメソッドでNoMethodErrorが起きるという事態。

そのため、大人しく絶対パスを使って書き直すことにした。

worker_processes Integer(ENV['WEB_CONCURRENCY'] || 3)
timeout 15
preload_app true

# listen Rails.root.join('tmp', 'unicorn.sock')
# pid    Rails.root.join('tmp', 'unicorn.pid')
listen '/home/user/project/tmp/unicorn.sock'
pid '/home/user/project/tmp/unicorn.pid'

before_fork do |server, worker|
  Signal.trap 'TEAM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill('QUIT', Process.pid)
  end

  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothind. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

stderr_path File.expand_path('log/unicorn.log', '/home/user/project/')
stdout_path File.expand_path('log/unicorn.log', '/home/user/project/')

これで解決。

おわりに

環境変数を設定すればいいのかもなーと思いました。

本番環境ではそれで行こうかな。

【Git】現在のブランチを取得して、git branchを打たないようにする

どうもてぃです。

皆さん開発してますか?僕は全然出来てません。

時に開発すると、自分が異常にgit branchをしていることに気づき、もうどうしようもないくらい同じコマンドを打ちたくない気持ちでいっぱいだったので、今回それを解決しました。

参考

すでに神がいました。

blog.penginmura.tech

こちらを参考にさせていただきます、ありがとうございます。

やったこと

aliasを作成して、push時、pull時にbranchを打たなくていいようにします。

alias.bashrcへ記載します。それぞれの環境で.bash_profileなどに書き換えてください(alias書いてるとこならどこでもいいんじゃないすか)。

alias push="git rev-parse --abbrev-ref HEAD | xargs git push origin"
alias pull="git rev-parse --abbrev-ref HEAD | xargs git pull origin"

git rev-parse --abbrev-ref HEAD で取得したブランチ名をxargsコマンドで渡してあげる。これだけ。

終わりに

pushするときに多用していたgit branch、その後にコマンドラインにあるブランチ名をコピーしてペーストする手間をなくしました。

これでbranchの煩わしさから逃れられますね。

…checkoutするときにはgit branchが必須なんですけど。

【備忘録】Railsでcheck_box_tagがfalseのときもパラメータを飛ばしたい

Rails速習実践ガイドめっちゃいいね、どうもてぃです。

さて、昔実装したのに、しばらくやってないと忘れることよく有りますよね。

今回は備忘録として忘れてたことを書きたいと思います。

環境

やったこと

check_box_tagでパラメータを飛ばす場合、デフォルトではチェックのついたものしか飛びません。ということを完全に忘れていて、軽く30分くらい悩みました。

なので、適切な対処が必要。

まずはcheck_box_tagのリファレンスを確認。おなじみのrailsdocです。

<%= check_box_tag 'page[freezeflag]', true, false, {} %>
# <input id="page_freezeflag" name="page[freezeflag]" type="checkbox" value="true" />

これ使ってみます。

check_box_tagの第一引数はパラメータのkey名 & 属性のIDとname、第二引数は渡す値、第三引数は初期値、第四引数は状態を表してます。

チェックがついていると、strongparameterの中に

{ "page" => <ActionController::Parameters { "freezeflag" => "true" } permitted: false> }

という形で入ります。チェック無しだとそもそも、params["page"]nilになります。

これはデータを更新する上で不便。チェックがあるかどうかで無駄な処理を書かなきゃいけないのはスマートじゃないです。

それを解消するのがhidden_field_tag

必ずcheck_box_tagの前に設置しましょう!

それが以下。

<%= hidden_field_tag 'page[freezeflag]', false %>
<%= check_box_tag 'page[freezeflag]', true, false, {} %>
# <input id="page_freezeflag" name="page[freezeflag]" type="checkbox" value="true" />

check_box_tagにチェックが入らなければ同じ名前のhidden_field_tagの値(false)がパラメータとして飛ぶ。

逆にチェックがついていればcheck_box_tagの方で値が上書きされるという感じ。

必ずnameは同じにしないといけないことに注意。あと最初に言ったけど、hidden_field_tagの位置にも注意。

これで今回の要件を満たせます。

番外編(おまけ)

素晴らしいメソッドを見つけました。

ActiveRecord::Type::Boolean.new.castです。

以下の記事に書いてありました。素晴らしいです。ありがとうございます。

qiita.com

なので、今回飛ばしている値を変更します。

<%= hidden_field_tag 'page[freezeflag]', 0 %>
<%= check_box_tag 'page[freezeflag]', 1, false, {} %>
# <input id="page_freezeflag" name="page[freezeflag]" type="checkbox" value="true" />

これで、パラメータとしてチェック済みの時は文字列の1、チェック無しだと文字列の0が飛びます。

上の記事のように、models/applilcation_record.rbへ専用のメソッドを書いておくと。。。

def checked?(data)
  ActiveRecord::Type::Boolean.new.cast(data)
end

checked?の引数に飛んできたチェックボックスのパラメータを渡すとtrue or falseを判定してくれます。

すばらしい。感動しました。