haayaaa’s diary

書きたい事があったら気軽に書いて行きます。普段は渋谷でRailsを使ったお仕事してます。

Rubykaigiの日記①(コード懇親会編)

rubykaigiのコード懇親会の中で、Rubyの標準ライブラリであるcsvライブラリにコントリビュートしましたっっw

下の画像がそのプルリクがマージされたスクショです!!!

gyazo.com

 

このプルリクを出すまでのプロセスで分からないことが多すぎ&コード懇親会来ていた人達レベル高すぎで、途中とても惨めな気持ちになっていたのですが、色々教えてくださったyuguiさんのおかげで無事プルリクがマージされるところまで達成できました!!!

思わず感極まって涙してしまいましたっっw(比喩ではありません)

 

 

人生初OSSコントリビュートがrubyの標準ライブラリになりました!!!!!!

yuguiさん本当にありがとうございます!!というお気持ちです!!!

 

また、homebrewをつかわずにrubyを手元に落として使える状態にしたのですが、未知なことが沢山ありました。

(結果的にプルリクを投げる事になったのはruby/csvリポジトリだったので、ruby/rubyを落とさなくても大丈夫だったのですが)

 

ruby/rubyリポジトリをhomebrewをつかわずにコードを動かして試せる状態にするまでの手順をメモしておきます!

(理解が追いついていないため雑なメモですw)

git clone --depth=10 https://github.com/ruby/ruby.git

cd ruby

brew install autoconf bison make

autoconf

mkdir -p build; cd build

../configure --prefix=$HOME/local/ruby

make

cd build

make -j 5 install-nodoc

 

 

5月はOSS Gateに勇気を出して申し込んでみたい気持ちです!!

 

また、自分は今までコードを読んでもプルリク送るべき部分が全くわからなかったのですが、ドキュメントなどで"TODO"と書かれている部分は積極的に書き足してコントリビュートして良い部分だと知れたので、これから時間がある時はやってみたいと思います!!

 

 

NKFで文字コードを変換する

csvのインポート・エクスポート処理でshift-gisUTF-8に変換する必要がありました。

しかし、文字コードについてよくわかっておらず、色々教えてもらいました。

今回はその内容について書き留めておこうと思います!!

 

 

NKFとは

ものすごく古い漢字コード変換プログラムである nkfRuby から用いるためのライブラリだそうです。

 

使い方

 使うには require 'nkf' して、

NKF.nkf(オプション, 文字列)

としてあげれば文字コードを変換してくれます。

 

以下は実際に自分がNKFを使った時のコードの一部です。

jobでcsvを読み込んで、その内容を保存する時に使いました。

 

require 'csv'
require 'nkf'

class ClientImportJob < ApplicationJob
include ApplicationHelper
queue_as :default



def perform(client_import)

  略

temp_path = @client_import.import_file.url

error_text = ""
csv_text = File.open(temp_path).read
rows = CSV.parse(NKF.nkf('-w -x', csv_text), headers: true)



end
end

 

 上のコードでは、-wと-xオプションを使いました。

それぞれ、

-wはUTF-8 を出力する(BOMなし)、

-xはX0201片仮名(いわゆる半角片仮名)をX0208の片仮名(いわゆる全角片仮名)に変換せずに
出力する、と言うオプションです。

これ以外にもたくさんのオプションがあります。以下のリンク先にオプション一覧がまとまっております。

docs.ruby-lang.org

 

 

文字コード難しい。。。!!

 

 

 

 

 

 

 

StringクラスのメソッドについてNerima.rbで勉強した!

本日@neko314_さんが主催してくださった、Nerima.rbの第一回に参加してまいりました!!

今回は、RubyのStringクラスのメソッドについてみんなで勉強しました!

 

普段から使っているはずのStringクラスにも関わらず、初めて見るメソッドがたくさんありました!!!

以下は、ルリマ(https://docs.ruby-lang.org/ja/2.6.0/class/String.html)に載っているメソッド一覧です。

 

特異メソッド

new try_convert


インスタンスメソッド

% * + +@ -@ << concat <=> == === =~ slice = ascii_only? b bytes bytesize byteslice capitalize capitalize! casecmp casecmp? center chars chomp chomp! chop chop! chr clear codepoints count crypt delete delete! delete_prefix delete_prefix! delete_suffix delete_suffix! downcase downcase! dump each_byte each_char each_codepoint each_grapheme_cluster each_line empty? encode encode! encoding end_with? eql? force_encoding getbyte grapheme_clusters gsub gsub! hash hex include? index insert inspect intern to_sym length size lines ljust lstrip lstrip! match match? next succ next! succ! oct ord partition prepend replace reverse reverse! rindex rjust rpartition rstrip rstrip! scan scrub scrub! setbyte slice! split squeeze squeeze! start_with? strip strip! sub sub! sum swapcase swapcase! to_c to_f to_i to_r to_s to_str tr tr! tr_s tr_s! undump unicode_normalize unicode_normalize! unicode_normalized? unpack unpack1 upcase upcase! upto valid_encoding?

 

 

これらのメソッドについて実際にirbで動かして挙動を確認していきました!

文字コードの仕組みに関わる部分の話や、処理速度の話、似ているメソッドのと良い使い分けの仕方、現場での活用法、正規表現を組み合わせた活用法など、自分だけでは気づかなかったであろう事についても勉強会の皆さんのおかげで知ることができました!!

 

また、前に話題 (?)になっていた、寿司ビール問題にも実際にコンソールで動かして確認してみました!

以下のリンクがその時のスクショを貼ってくれているツイートです!

 

勉強会の内容はhackmdを使い、皆で要点やコンソールで試した内容を書いていきました!

(自分は聞くことに意識が向きすぎてあまり書けなかった。。。!!)

以下がそのhackmdのリンクです!

hackmd.io

 

 

 練馬はとても雰囲気のいい街でしたし、Stringクラスのメソッドについて実際に仕事で使えそうな内容から、いつ使うのか謎な内容まで楽しく学ぶことができたので参加してよかったです!!

 

 

 

CarrierWaveでアップロードしたファイル名をそのまま表示させたい

CarrierWaveでアップロードしたファイル名を表示させたかったのですが、

そのままカラム名を表示してしまうと、

絶対パス表示&ファイル名が日本語だった時文字化けしてしまい、なんとか通常のファイル名を表示できないか調べました。

ググってもなかなか出てこなかったので、頑張ってコンソールで試しまくりましたw

結果、以下のように変更して問題なく表示させることができました!!

 

 

 before(絶対パス表示&文字化け)

td = client_import.import_file

 

after(ファイル名のみ!!)

td = client_import.import_file.file.basename

 

 

なんかもっといい方法ありそうですが。。。

 

 

 

 

 

読みやすい条件の書き方にする

ビューで 'Loading...' という文言を表示させる条件を、以下のように書いてしまっておりました。

- unless (@menus.include?(@menus_last) || @menus.length == 0)
.page-load-status
.infinite-scroll-request
| Loading...

自分でもこのunless文を書くにあたって、ベン図を使いながら考えないと分からないくらい、直感的でない書き方をしておりました。

 

このコードをレビューもらった際、どう書くべきかについてアドバイスを頂きました!! 

具体的には、以下のような内容です。

(本当はもっと具体例交えてわかりやすく丁寧に書いてもらいました)

  • unlessに複数条件設定すると可読性が下がる・理解しづらいのと保守性もいまいちなので、複数条件使うときはifに直した方が良い
  • ActiveRecordのメソッドを使ってスッキリ書けるなら書く
  • 好みと肌感覚的な部分になるが、viewのロジックが複雑になった場合はhelperに移すのが良い

 

 

実際にアドバイスをいただいた後書き直したものが以下です。

- if @menus.exclude?(@menus_last) && @menus.present?
.page-load-status
.infinite-scroll-request
| Loading...

初めは自分でもベン図を書かないと理解しづらかった条件文が、直感的にわかるようになりました!

 

スッキリかけたので今回はヘルパー化はしませんでした。

自分にも他人にも読みやすいコードを書いていくよう意識していきたいです!!

 

 

 

 

コントローラを分けるタイミング

本日、あるアクションを実装した部分について、別のコントローラに分ける方が良いというアドバイスを頂きました。

具体的には別のモデルの処理であるにも関わらず、1つのコントローラの中で実装してしまっておりました。

 

その際に参考文献として以下のリンクを教えて頂きました!

 

 

postd.cc

 

 

・なるべくRESTの考えに乗っ取った形でアクションを定義していく

・1つのコントローラに多くの処理を任せすぎない

・コントローラが元々持っているRESTアクションやデフォルトの5つの機能にはないメソッドを付け加えたいと思ったら、新しいコントローラに処理を分ける

・フィルタのように、状態を変化させるような処理も別のコントローラに分けて良い

 

といったことを詳しく書いてくれております!

 

 

他の人と一緒にコードを書いていく時のマナーとして、これらのことを習慣にしていきたいと思います!!

 

 

 

 

 

postgresqlのセッションを切断

テストが実行できなくなってしまい、焦ることがありました。

 

ターミナル再起動しても相変わらずテストが実行されないままでした。

 

rake db:resetしようと試みてもエラーでリセットできませんでした。

しかし、ログをたどっていったところ、どうやらポスグレのセッションが何個も立ち上がり過ぎてしまっていることが良くなさそうだと思い、スレッドのセッションを切ることにしました。

その方法を書き留めておきます。

 

 

セッションを調べる

psql -d DB名 というコマンドでポスグレのコンソールに接続後、以下のコマンドでセッション一覧を表示させます。

SELECT pid FROM pg_stat_activity where pid <> pg_backend_pid();

 

$ psql -d hoge_test
psql (11.1)
Type "help" for help.

hoge_test=# SELECT pid FROM pg_stat_activity where pid <> pg_backend_pid();
pid
------
1388
1390
1264
1812
3039
1033
1550
1040
3146
2418
3279
1386
1385
1387
(14 rows)

 

セッションを切断する

以下のコマンドでセッションを切断します。

SELECT pg_terminate_backend(pidの番号);

 

  hoge_test=# SELECT pg_terminate_backend(1388);
pg_terminate_backend
----------------------
t
(1 row)

 

これで無事テストが動いてくれるようになりました!!

 

 

感想その他

なぜこんなに余計なセッションが生まれてしまったのか原因が良くわかっておりません。。。

テストの中の "js: true" の記述によって新しいスレッドが立ち上がってしまっているっぽかったのですが、どうするのが正しいかは引き続き調べていきたいと思います。