rails のサーバー立ち上げようとしたらセグフォした件

Railsでセグフォした

teratail.com

rails s ができません。mysql2-0.5.1/lib/mysql2/client.rb:90: [BUG] Segmentationエラー

いやいや、RailsSegmentation Faultってそんなわけないでしょ??????????

お。??まじやんwwwwwwwwwwwそんなことある????wwwwwwwって感じでした

以下質問文引用

開発中に突然warning: already initialized constant FileUtils::RUBYエラーが出てしまい、ruby、railsを再インストールしました。

そうしたところSegmentation fault at 0x00000000000000と出てしまっています。

どうもmysqlとの紐付けがうまく行ってないのかと思いますが、原因不明です。

rails sをしてもサーバーを起動させることができないでいます。 

どなたかご助言をいただけますと幸いです。

ふむふむ。よくわからんがエラー前に何かしたんじゃないの????という感じですねw ただ話を聞いていると特に何もしていないっぽかったのでよくわからんという感じです。w

...エラー文

vendor/bundle/ruby/2.4.0/gems/mysql2-0.5.1/lib/mysql2/client.rb:90: [BUG] Segmentation fault at 0x00000000000000
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]

-- Crash Report log information --------------------------------------------
   See Crash Report log file under the one of following:                    
     * ~/Library/Logs/DiagnosticReports                                     
     * /Library/Logs/DiagnosticReports                                      
   for more details.                                                        
Don't forget to include the above Crash Report log file in bug reports.     

-- Control frame information -----------------------------------------------
c:0043 p:---- s:0315 e:000314 CFUNC  :connect
c:0042 p:0688 s:0303 e:000302 METHOD /Users/___/Desktop/lance_note/vendor/bundle/ruby/2.4.0/gems/mysql2-0.5.1/lib/mysql2/client.rb:90 [FINISH]
c:0041 p:---- s:0289 e:000288 CFUNC  :new

ほぉ?なんかgemsの下のmysql2の中のファイルで死んでるっぽいですね?。 とはいえ直前まで動いてたらしいし動くでしょ、普通w

たまたま該当の質問者と知り合いだったので連絡をしつつ解決した経緯について触れたいと思います。

なんとなく現状のMysqlRailsの疎通を確認したかったので

$ rails s
$ rails c
$ rials db:console
$ rails db:migrate:status

などのRailsコマンドを叩いてもらうと rails cだけがうまく通るみたいです。 Rails本体はうまく動いてるっぽいですね。RailsとDBを繋げようとすると◯ぬ。

$ mysql -u root;
$ show databases;
$ use sample_db;
$ show tables;

のようなMysql自体へのアクセスやSelectクエリなどは問題なく動くみたいです。

RailsMysql繋げようとするとセグフォする?????????!w

この時mysql2のgemのバージョンの問題かと思って

0.5.1
0.5.2

などに変えたりしてもエラーが発生してました。

fumihumi.hatenablog.com

などを試してみたりしてもらっても変わらん。 なるほどよくわかrん

結論

...mysql2のGemのVersionもう一個下げてみますか?と思い。 0.4.10 に下げてみてもらったところ、解決されたようです。

うーん謎いですね。特にISSUEなどになってるわけでもないので特定の環境下にて再現されるものなのかもしれません。 ただ、 rails puma segmentation fault ってググってもあんまりヒットしなかったのでとりあえず書いてみました。

何かわかる人いたら教えてください。

iOSシミュレータで開発効率が100倍増しになった話

TL;DR

Web開発するのに、スマホ画面での検証しないと行けないじゃないですか。 いままで chrome, Chrome Canary, safari, secretWindowとかを駆使して iphone5, 7, 7plus, Xのサイズ試してたのですが、◯ぬほどめんどくさいなぁと感じてしまったんですよね。(遅い) それを解決しようってのが今回の話です。

きっかけは↑の記事でのシミュレータをフルウインドウでひらくというもの。 ↑の状態で シミュレータ複数横並び にできたら幸せじゃないですか!

という訳でやってみました!

やったこと。

https://github.com/facebook/FBSimulatorControl

今回は使ったのは FBSimulatorControlというFacebook社が提供してるOSS。 このOSSbrew を使って入れてました。

  $ brew tap facebook/fb
  $ brew install fbsimctl --HEAD

$ fbsimctl list fbsimctlコマンドにlistを渡すと起動可能なシミュレータの一覧を取得できるみたいです。

@fumihumi:fbsimctl list | grep iPhone
022068FE-C8EB-4B70-A248-59050F47DEBB | iPhone X | Booted | iPhone X | iOS 11.4 | x86_64
B4D8BDFD-0F86-411A-986F-524C3B646547 | iPhone SE | Shutdown | iPhone SE | iOS 11.4 | x86_64
5E5E1123-AEF2-4765-90AA-B6C82ED55ABF | iPhone 8 Plus | Shutdown | iPhone 8 Plus | iOS 11.4 | x86_64
BDC8695E-568C-454E-9DD8-8732677B7A9D | iPhone 8 | Shutdown | iPhone 8 | iOS 11.4 | x86_64
CA9F509D-A76B-4708-B7B1-07341D8FC324 | iPhone 7 Plus | Shutdown | iPhone 7 Plus | iOS 11.4 | x86_64
DA208130-4BED-433B-89CB-BA35C0CBC5A9 | iPhone 7 | Shutdown | iPhone 7 | iOS 11.4 | x86_64
EB6362A3-BBA7-45DD-95AF-2AFA91AAD624 | iPhone 6s Plus | Shutdown | iPhone 6s Plus | iOS 11.4 | x86_64
2DE031F8-DCDB-4CD2-91B1-C8915F3E3644 | iPhone 6s | Shutdown | iPhone 6s | iOS 11.4 | x86_64
2EBD9CF9-1654-4E18-8017-53A2901F9CC9 | iPhone 6 Plus | Shutdown | iPhone 6 Plus | iOS 11.4 | x86_64
D6F59370-3C52-4DC0-823C-85B5D20E222A | iPhone 6 | Shutdown | iPhone 6 | iOS 11.4 | x86_64
DD24F91C-A6BF-470D-B8A9-B288A8D215CC | iPhone 5s | Shutdown | iPhone 5s | iOS 11.4 | x86_64
UUID:(識別子的な何かっぽい)
機種:(AppleTV, iPad Pro, iPhone, AppleWatch)など
起動状態:(Shutdown | booted)

などが乗ってますね

まぁ

fbsimctl list | grep -e 'iPhone X' -e 'iPhone SE' とかでグレップした上でそのUUIDを元に

fbsimctl B4D8BDFD-0F86-411A-986F-524C3B646547 2DE031F8-DCDB-4CD2-91B1-C8915F3E3644 boot

のように fbsimctl UUID boot とすることで複数の端末をエミュレートできます。

結局なにしてたの?

Web開発で複数のユーザで確認したいとき。 ブラウザでタブ開いて確認してもいいんですが、シークレットウインドウつかったりChrome, safari, firefoxで別ユーザでログインしたり、大変。。。。。

そんな時にiPhoneシミュレータでできると便利なんですよね。

詰まったこと

$ brew install fbsimctl --HEAD がうまくいかなかった

org.carthage.CarthageKit/dependencies/GCDWebServer: Operation not permitted

というエラーが出ていた、

sudoつけて、Installしようとしたんですが、 sudo brew install 〇〇 ってダメなんですね。初めて知りましたw

↑のエラーは Carthage を消せば良さそうみたいです。

$ brew uninstall --force carthage
$ rm -rf ~/Library/Caches/org.carthage.CarthageKit

特に Carthage に思い入れないので容赦なく消してやりました。 まぁ大丈夫っしょw。 iOSエンジニアは少し躊躇したりするんですかね? よくわかりませんけど 頑張ってください。。w

まとめ

iOSシミュレータを使ってスマホレイアウトの確認をすると、想像以上にやりやすい! (最近ChromeのDeveloperToolがより便利になってなんとも言えない気持ちになってる)

gitのssh_key作ったのにssh -T で permission deniedされた。

SSHKeyを追加したかったんですけど

qiita.com

↑の言われるようにやってました 

  ssh-keygen -t rsa -b 4096 -C  '#{めあど}@#{こめんと}'
  pbcopy  < github_id_rsa.pub
  # ブラウザでGithubのSSH登録

疎通確認をする↓

$ ssh -T git@github.com
git@github.com: Permission denied (publickey).

# なにやらうまくいかないけどとりあえず管理者権限でやったろ

$ sudo ssh -T git@github.com
Password:
The authenticity of host 'github.com (192.30.255.112)' can't be established.
RSA key fingerprint is SHA256:nThbg~~~~~~~~~~E5SY8.
Are you sure you want to continue connecting (yes/no)?
Host key verification failed.

うーん。うまくいかない。 sshの鍵は作ってるんだけど手元のpcでちゃんと認識できてないっぽい?

$ ssh-add -K ~/.ssh/github_id_rsa
Enter passphrase for /Users/{ユーザー名}/.ssh/github_id_rsa:
Identity added: /Users/{ユーザー名}/.ssh/github_id_rsa

ってやったらできました。

ssh-addの-Kはなくても問題ないんですがpc再起動すると読み込みに失敗したりするのでオプションつけたほうがよさそう

うーん。よくわからん

ServerSonic2018に参加しました!

表題の通り、先日実施されたServerSonicに参加しました〜

hackerslab.aktsk.jp

公式レポートの発表のあとにブログかいてしまった。。。もっと早く出すつもりだったのに......

2018年8月25日(土)〜 26日(日)にて開催された、Akatsukiのサマーインターンシップ SERVERSONIC2018に参加しました!

とても嬉しいことに優勝し、景品としてPS4 proをいただきました!!!!!! 廃れない程度にいっぱい遊びたいとおもいます!!w

..最後のスコア載せとこ..

TL;DR

8/25~8/26の2日間Akatsuki社のサマーインターンシップServerSinicに参加させていただきました!!!

インターンシップに参加し、

自分の足りないものや、自分の中での好きなことといったものに出会えたのかなと思います。 そこでそれら言語化したく思いブログに書いてみようと思いました。

2人1組のペアになって 八月のシンデレラナイン のプロダクトコード(バグ埋め込み済?)を改善するというインターンシップでした! ISUCONとかに近いのかな。自分はISUCONでたことないのでよくわからないですが

以下のようなことをつらつらと書いていきたいと思います。

  • 簡単に概要
  • 前半の内容
  • 後半の内容
  • どんなことしたの
  • なにが大変だったの
  • どんなこと頑張ったの
  • 知見は?
  • 得られたもの

簡単に概要

以下インターンシップ募集ページより引用

大量トラフィックを処理することが求められるゲームサーバーアプリケーションの性能改善方法を学び、 公開中の『八月のシンデレラナイン』プロダクトコードの性能改善にチーム対抗のコンテスト形式で取り組んでいただきます。

実際に高負荷環境での性能改善に取り組んでいるエンジニアからの講義や、 社内のエンジニアとカジュアルに交流できる懇親会も開かれます。

優れた改善ができた場合は実際のプロダクトに取り入れる可能性もあり、 優勝チームには賞品が贈られます。

ふるってご参加ください。

> 詳細はこちら:https://aktsk.jp/recruit/new_recruit2020/serversonic2018/

というようなものです。 一言で言えば, 八月のシンデレラナインにCommitしようぜ!!!!!!! というような趣旨。 学生向けにわざと n + 1問題や、cacheをあえてしていなかったり、処理が遅くなるような いじめ 工夫がされているプロダクトコードに対していろいろ頑張っていくコンテストがメインのインターンシップでした!

ゲームAPIソースコードがみれるというだけでも学生にとっては最高な環境にも関わらず。 昨年から始まった?このインターンシップは商品が とても豪華 で今年の優勝者には n社のSw***h, であったり、S社の PS*であったり, みんな大好き 米国Ki***is社のエルゴノミクスキーボードといったものが贈呈される (らしい) (来年はわからない)きっとあるよ!! といった学生が燃え上がる景品が用意されてました!!!!!!!!!!!!!!! (最高!w )

ちなみに八月のシンデレラナインはガチャでSSRが出やすいアプリ(体感)なので個人的に幸せ指数があがるアプリです!!w (試行回数が多いだけではないはず) 余談ですが初日終わった後に10連ガチャ回したらssrが二枚出ました!w。


実際にインターンシップの内容は以下にまとめていきたいと思います。 ざっくりまとめると講義コンテストの二部だてになっていました

前半講義

  • 1つめの講義 ```
  • 開発環境構築
  • k8s入門
  • ゲームサーバのイロハ
  • 負荷削減講座 ```

  • 2つのめ講義 ```

    • プロファイラを使った計測の方法
    • Gemライブラリの最適化の方法
    • (余談)大規模Railsアプリケーションの最適化事例 ```

講義は前半と後半で、インフラ周りの話メインの午前と、後半はRubyでの高速化をする方法を教えていただきました。 (どこまでかいていいんだろう。わからないので簡潔に書く)


前半の講義では主に開発環境とCI環境や実務でのインフラ構成などの話とざっくりとチューニングに関するアレコレを話していただけました。

今回の環境は k6という負荷テストツールをつかってRailsアプリケーションに対して負荷をかけるものです。 (https://qiita.com/szk3/items/c1172ef3d182d7fe6868)

k8sのコンテナの中にk6の負荷テストがあるpodがあり、それとは別にRailsアプリケーションのpodがあり、Railsコンテナ、Mysqlのコンテナ, Memcachedのコンテナ, Redisのコンテナが用意されているものです。 ローカル環境はDocker for Mack8sを起動し, CIはGKEを使っているそうです。 docker使ってるのに開発環境の構築難しいの本末転倒のような気がしてしまった。仕方ないw 講義担当者が今回のインターン用の環境などを用意してくださっていたようで、 この環境で楽しんで遊んでください。というようなメッセージがありましたwww

普段RedisやMemcacheといったものを独学の環境で実装したことがないため mysqlとの違い、それぞれの用途わけやメリット・デメリットを聞きました。 個人的にRedisとMemcacheって同時に使わないと勝手に思い込んでいたので別の用途として共存するという選択肢を改めて知れました。


後半の講義は rubyのGem ( gem 'rack-lineprof', github: 'kainosnoema/rack-lineprof' ) ( https://k0kubun.hatenablog.com/entry/2014/09/22/020942 )

Sinatraアプリのプロファイリングにはrack-lineprofが便利

とかいてありますが、Railsでもちゃんと使えました! lineprofを使うと1つ1つのメソッドや処理(Enumerable#map)などの実行速度を把握することができ、 処理速度を読み込み遅いやつがlogが赤色や黄色になる便利なgemでした。

また、Gemライブラリの最適化では、Rubyオープンクラスの拡張、モンキーパッチの当て方の話 ( https://qiita.com/kidach1/items/b1672f1c16e2d15f2d9c ) 参考記事さがしてたらアカツキの記事というw

rubyのメソッドの読み込み順序や、クラスのよみこみ順序といったメタプログラミング入門を話していただけました (なんとなくわかったような気がしたような気がする) 最近efecteve rubyを読みはじめたのでかろうじて理解ができたような気がするのですが実際にオープンクラスの拡張などを実際にしていないので勉強しようと思います。

また実際の業務の際にパフォーマンスチューニングをする際の心得や、注意事項。 どんなことを注視してログを見ているのか。このツールが便利、等の話をしていただけました!

闇雲にソースコード変えるくらいなら実測値から原因を絞り出す、とのこと。 本当に遅い部分というのはとある処理のなかのボトルネックを潰せば結構早くなるとのことでした。 (ボトルネックを意識することの重要さをかなり語っていた。。。)

のような講義を初日の夕方くらいまでしていました。


後半の内容(ここからコンテスト)

後半はインターンの募集要項にあるように (以下抜粋) 公開中の『八月のシンデレラナイン』プロダクトコードの性能改善にチーム対抗のコンテスト形式で取り組んでいただきます。 というコンテストです!

内容はいたってシンプルでGithubにPushしたらCIが回って点数を各チームのSlackチャンネルに投げてくれるというもの。 初期値が33000くらいで始まりこの数値を締め切りまでに最速にしたら勝ちというものです。

余談ですが、コンテスト中にCIのバグを踏み抜いた(?)チームがあるらしく 途中でAPIのテストが追加されましたw。

自分が変更したコードも見事↑によってコケたので大変だった。w

どんなことしたの(改善手法について簡単に)

自分はまずLineProfの内容を精査し明らかにボトルネックっぽいものをGithubISSUEにしてました。 チームメンバ(以下K氏)にはサーバーログを見てもらい N + 1レンダリングに時間かかっている箇所、ボトルネックっぽい場所をログ実際にテスト走らせながら確認するなどの作業をコンテスト開始から1時間?くらいしてました。

本来であればLineProfの結果を最後まで確認し精査をちゃんとするべきであるのに、時間に追われていることもあり、 3/5くらいのエンドポイントくらいしかちゃんと見ておらず、その先は 目グレップ していましたw。(単純にこの段階でログの追い方が下手だった。。。。。)

とりあえず初日はソースコードの概要把握 (これがしんどい) とDBのindex調査、 n + 1の改善をメインに担当と、 K氏がRails経験が浅かったので彼が実装したい内容(SQL)をRailsに翻訳することをしていました。 自分のRails力がなさすぎて一緒にググったりしてしまったり。。。(tsurai)

初日はそれぞれ一つづつくらいのPRを投げて終わった気がする。

帰り道や、自宅で1日を振り返っているとLineProfの見方がおかしかったんじゃないかと思い始めたので翌朝出社と同時に改めて調べ直しました。

今までは全体的に目グレップしていたのですが、ちゃんと各エンドポイントごとにログファイルを出し分けて その中で問題になってる箇所を目grepして APIのエンドポイントとどのメソッドが遅いのか問題点を探し出しました。 また同時にbulletのログも確認するようにし同様にメソッドレベルで問題点をまとめました。

このファイルを元にあらためてぼんやりながめていると
・あるAPIn + 1しまくっていることに気づいたり、
レンダリング速度が異常におそいAPIあったり。
・なんかしらんけどSQL死ぬほど吐いてたり。
といったやばい状況だということに改めて気づいてしまいました。

自分が n + 1対応と、レンダリング周りを調査しつつ、
SQLが爆発している箇所をk氏にお任せしました。(大変そうだった箇所をお願いしてしまった。)

ただ、分担してから少しすると、k氏の担当箇所が想像以上に大変そうかつ、Railsの手法をしってないと難しそうということにきづいたのでモブプロっぽい感じで二人モニター見ながら作業をするようにしてました。
(多分インターン生ぼくだけモニター使ってなかったw)基本的に役割分担してやってるのが多かったのかな。

SQLが爆発してたのは
- 単純に n + 1の countクエリを投げていたってこと
- メモ化をしておらず毎回クエリをぶん投げているため死ぬほど重くなっていたこと
この2点が原因でした。 (記憶の中では)

このPRだけで結構点数がのびたのでチャレンジしてくれたk氏には感謝です。。。。。

大変だったPRは↑がメインだった記憶があります。 あとは
ひたすら n + 1対応の includesをしたり(めっちゃ書いたw)
includesをいろいろしすぎてうごかないから preloadとearger_loadでごにょごにょしていい感じにしたりした。
キャッシュできそうな変数はひたすらメモ化した。
Enumerable#selectはActiveRecordのWhereに変えたりしてました。

Jbuilderのテンプレートのよみこみが遅かったので eachしてpartialを読み込んでいる箇所を直接殴り書きにしたり(若干早くなった)

ruby before: json.samples partial: 'samples/sample', as: :sample after: samples.each do |sample| sample.*** end

以下記事を参考に無理やりgsubしたり(ほとんど変わらずw)

https://blog.freedom-man.com/jbuilder-n1render/

records = render partial: 'api/hoge/record', collection: @records json.hoge JSON.load("[#{records.gsub('}{', '},{')}]")

のようなことやpartialの引数はcollection使うと良いとか書いてあったので使ったりしたり。

みたいな地道なチューニングをひたすらしていました。


最後に結果発表と同時に 田中さん(CTO)から、順位に限らず参加者からの優れたコミットの発表(優秀コード部門、ネタ部門など)があり、そのコードを書いた参加者が意図を話して、2日間を振り返りました。

自分が頑張った箇所などが発表されると嬉しいですし、周りのチームとのアプローチの違いなどもしれてとても面白かったです。

なにが大変だったの

げーむAPIならではのシャーディングとか。
そもそも速度改善ってあまり意識したことがないのでボトルネックさがすのがつらい。
複雑なDB構成を確認するの大変w
Railsの書き方をすると簡単にデータ取得できるのに n + 1になったりw
あとは単純に1日2日で理解が追いつくような規模のアプリではなかったので今改善しようとしている箇所の影響範囲などを調べるのが難しかったです。

どんなこと頑張ったの

やったこととしては前述した通り

  • ひたすら n + 1対応の includesをしたり(めっちゃ書いたw) includesをいろいろしすぎてうごかないから preloadとearger_loadでごにょごにょしていい感じにしたりした。
  • キャッシュできそうな変数はひたすらメモ化した。

    といったようなチューニングにおける基礎的な部分とボトルネックを探すことを頑張っていました。

特に初日のログの追い方がわるかったこともあり2日目は
- それぞれのエンドポイントごとのログに分ける。
- おそくなってる部分を確認し、そのメソッドに問題があるのか前後処理に問題があるのか切り分ける。

→その上で改善するべきかどうかを判断するなどをしていました。

ゲームロジックに関わってくる処理は比較的重い処理になりがちな印象をうけ、 できる限り複雑なロジックには触れず(影響範囲が測れないため)、ピンポイントで改善できそうな箇所を探し、改善をしていました。

感じたことなど

チューニングは難しそう。という先入観がとても強かったのですが、実際にやってみると いまの自分の知識であってもある程度は可能なんだなということをしれました。 まだまだ改善できるような箇所はあったと思うのですがどこをどう改善すればよいのか見当が付いていないため、仮にあと1日あったとしてもスコア的にはあまり変わらないのかな。。とか思っていたり。 圧倒的なRails力・Ruby力不足です。

また、想像以上にボトルネックって探しにくいんだなというのが率直な感想でした。 newrelicのような可視化ツールの偉大さを改めて感じつつも、ログを見ることの重要さをも感じました。 基本的な情報はすべてログにあるとおもうのでそこから必要なものを知るのは事前知識とログ解析力と目グレップ力なのかなと。 ログの中から必要な情報を探しだすことの大変さとそれの重大さを改めて知るきっかけになったのはとてもよかったです。

まだまだ本質的な部分はわかっていないのですが、基本的なチューニングの先は Railsのベストプラクティスに従いつつもRubyでのメタプログラミング的なことをしてアプリケーションへの最適化をすることが最適解なのかな。というのが個人的な感想です。 基本的な思想はRailsWayに従いModelのConcernなどを利用しつつもクラスの拡張などを利用し既存メソッドを書き換えて処理を軽くするといったことができるのかな。。?

単純に自分自身のRailsへの理解であったり、Rubyへの理解の甘さが今回のスコアがもっと伸びなかった原因なのかなと思っています。 もう少しRubyの深い部分について学んで行こうとおもいました。

最後に

githubへのpushをトリガーにCIが回ることで自分の作業がプラス方面になっているのかマイナス方面になっているのかがすぐにわかるシステムでとてもやりやすかったです。 点数という数値化されたものだったのでそれが1000あがるだけでよっしゃ!!となるのでそれがとてもモチベーションとなっていました。

とても楽しかった!!

このブログは誰宛のものなのだろう。 自分の感想なのか..

インターン終わってから一週間たってしまい気づいたら9月に。。なっていた。早い。 自分がやってたことなどの記憶が曖昧になりつつこの記事を書いてしまっていてなんともいえない気持ちになったw

今回学んだことを活かすためにisucon2018に申し込んだので次はアプリケーションレイヤだけでなくミドルウェア周りも調査できるのでいろいろ頑張りたいと思います。

エイチーム3Daysエンジニアサマーインターンシップ<Sembatsu>に参加した!

Ateam3Daysエンジニアインターンシップでの学び・記録

三日間の成果を一言で言うのであれば

今までの自分から一歩成長できた!

と言うんじゃないかと思います。

TL;DR

ご縁をいただき、8/3~8/5の三日間Ateam社のサマーインターンシップに参加することができました。

3日間の滞在費および'昼食'、'夕食'(名古屋めし)を負担していただき感謝しかありません。ありがとうございました。

インターンシップに参加し、

  • 今までの自分の感じていたエンジニアとしての働きかた。
  • 自分のなりたいエンジニア像

といったものの概念が再構築されたので言語化したく思いブログに書いてみようと思いました。

(見返してみると拙い文章かつ、とりあえず羅列したような箇所が多く見にくくなってしまって辛いw)

目次

  • 3日間の概要
  • 3日間の内容
  • 参加して感じた・学んだこと
  • その上で自分自身の今後について

3日間で何していたの?~概要~


参加者が全体で21名、それぞれ3人チームになり、チームごとにプロダクト改善を行いました。

HPからの引用ですが概要は↓になります。

 ・エンジニアコース(3days)
エイチームのエンジニアの仕事を3日間に凝縮したインターンシップを開催!
みなさんにはあるシステムに対する”ユーザが思う真の課題”を解決していただきます。
各チームにエイチームのエンジニアが入り、質問・相談などみなさんをサポートします!
エンジニアとしての価値を高めて、自分自身のスキルアップができるインターンシップです。


■エンジニア
エイチームのWebエンジニアの仕事を3日間に凝縮したインターンシップを開催!
みなさんにはあるシステムに対する”ユーザが思う真の課題”を解決していただきます。
・実装する力(技術)
・課題を見つける力(企画)
・解決したことをうまく伝える力(発表)
当日は、この3つの力を高めるためのコンテンツを複数用意。
各チームに現役プログラマーの社員が入り質問・相談などみなさんをサポートします!
Webエンジニアとしての価値を高めて、自分自身のスキルアップができるインターンシップです。

2020年卒業生向けにサマーインターンシップの募集を開始!

ATEAM SUMMER INTERNSHIP 2018

Ateam Lifestyle Advent Calendar 2017 学生満足度100%を獲得したインターンの裏話

↑を見てもらえば内容がざっくりとわかると思います

特に本題であるインターンの後半では、ユーザの課題とはというテーマで考え、議論し、ブレストし、出てきた改善案を実際にプロダクトに組み込むということをしました。

具体的にはどんなことをしていたの?


(注意:めちゃめちゃ長いです...www)

3日間を通して1つのアプリケーションに改善を重ね, より良いプロダクトにしよう。 というものでした。

初日と2日目の午前はすでに問題提起されている課題を解決するためのチケット型の開発。 2日目後半〜3日目の昼過ぎまでは自分たちで課題をさがし、その課題を解決するための機能を作るということを実装&プレゼンするものでした。

前半:チケット解決タスク

まず前半のチケット型の課題では vue on Rails という今風なRails製業務アプリに潜んでる既知のバグの修正や機能改善を加えるというものになっておりました。

個人的に React on Rails のプロダクトを触ったことはあるものの、 Vue on Railsソースコードはとても難しく感じ、一つ一つの機能を追うことに必死になっていました。 Vue.js使うなんて聞いてない。。。。。。。

ちなみにですが、僕のチームではまず、チケットを見渡し、'お!解決できそう'と思えたものを順番に着手し、実装に悩んだら相談する。といったスタイルで取り組みました。

チケットにはちょっとしたバグ?仕様漏れ?だったり、Railsのお作法に沿ってないが故のバグ、ユーザビリティの悪い処理だったり、...etc..多種多様なチケットが用意されていました。 (RailsができなくてもVueわかるだけの人がチャレンジできる感じなものもあった気がする......!? その逆も!)

初めてのVue.js難しいなぁと思いながらもVueのライフサイクルや構文について調べながら必死にもがいていましたw

チケットをたくさんこなしたわけではないのでチームメンバには申し訳ない気持ちになってしまいました。。自分の実力不足だなと痛感させられる前半でした。。

ちなみに順位は

初日終了時で、7位(最下位) -> 2日目の正午の段階で4位。

という結果に!(いい感じに挽回できた?!!)

後半:ユーザの課題を解決せよ!

後半では、実際に業務で使っているツールを改善しようというものです。 以下のような流れで行われました。

  1. ユーザへのヒアリング
  2. 追加機能の検討&&実装
  3. プレゼン

2日目の午後 ~ 3日目の14:30までという24h程度の時間のなかで機能の検討と実装をするという時間に縛られたハッカソンですね

※以下の内容は僕らが実際に行動していたことで 失敗? の経験です。

まずは実際に使っているユーザにヒアリングしました。 (Ateam社員:[エンジニア、マネージャ、CTO]といった方々)

- 普段どのようなことに使っているのか
  - 使う時に意識していることはあるか。
    - あるのであればどのようなことを意識しているのか。
    - 利用するシチュエーションが自分たちの考えとの相違があるのか。ないのか。
  - そのほかの利用用途があるのか
   - あるのであれば....
- また、事前にサクッと検討した機能があったら使うか?
  - プラスαどのような機能であれば使いたくなるか。

といったようなことを質問させていただきました。(詳細はアレがアレなので濁らさせていただきます。)

このヒアリングの際に聞いた内容を元に課題を考えました。

こんな意見を〇〇さんはおっしゃっていたよ
   → 〇〇さんも似たようなこと言っていたよ
 この部分てなんかアレじゃない?
   何が問題なんだろう?
   昨日が足りてないのかな?→こんなの増やしたらいいんじゃない?
 ここの部分。こうしたらさっきの解決しそうじゃない?

こんな機能があったらいいんじゃない?
この機能があればさっきの〇〇さんの悩み解決しそうじゃない?
あとはこんな機能とかも良さそう?
  →それならGem使えばすぐできそうなきがする

とかとか? を話していた気がします。(記憶が。。w)

このとき自分たちの担当のメンター(社員)から最終日の評価について以下のアドバイスをいただいておりました。

→ 見つけた課題に対して適切な機能かどうか(論理が飛躍していないか)
→ そもそも見つけた課題が表面的なものでないか(ありきたりな解決策になっていないか)

<評価項目>
・課題へのアプローチがよいか
・つくりきったか
・プレゼン力
・技術的難易度
・想像を超えた機能があったか

結論から言うとこのとき(20時)の段階の機能が 『想像を超えた機能があったか === 0 | 1 』 だったんですよね。

これはメンターから 1 on 1 面談の際に ど直球 に僕たち3人にそれぞれ伝えられましたw

チーム対抗戦なのにアイデアで負けてしまっていては、勝てない。やばい!www と思い残り90分なのに振りだしに戻りますwwwwwwwwww

ここからが本当の後半のインターンになる。 (2日目終了90分〜120分前?)

この考え直す時に何より大事にしたのは

  • ユーザの 本質的な不満 はどこにあるのか。
  • ユーザの 本当に求めている機能 はどんなものなのか。
  • そもそもユーザってなんで、このサービスつかってるの!
  • この サービスの価値 ってなんなの。

といったような、本来であれば 初期の段階でちゃんと考え込むべきポイント をひたすら再考していました。

先ほどまではソリューションレベルでのアイデアの具体化まで落とし込んでいたため内心すごいつらかった(メンタルがしんどい。。。w)。 そんなことは忘れ(るしか選択肢になく)、ユーザインタビューのメモを見返し何かヒントを探すという作業に戻りました。

ヒアリングした際のメモの中に

- なぜそのサービスを業務で使うんだろう?
- 業務でやる必要ってあるのかな
(と言うコメントをヒアリングタイム終了3秒前をもらっていた!のを思い出します。)

この二つについて考え直し、ブレストするということをギリギリまでしていました。。w 少し前までは空気がどんより(お通夜ムード)、だったのにブレストしていればお互いの考えが発散し。その中で別の意見が生まれる。 ポジティブな循環をしていました。そのため、お互いの意見に対してそれってこう捉えることもできるよね。と意見がより良い意見になり、別の視点からのアイデアと昇華されていました。

そんなような 締切駆動の僕たち が考えたことは

  • ユーザにとってこのサービスは。〇〇な価値がある
  • 会社にとってこのサービスは。 〇〇な価値がある

という結論に終着し、 その価値を200%活用するための機能作る 創ることにしました。

簡単に実装内容だけ書くと

RailsからPythonAPIサーバーたててごにょごにょしてRailsに返して、RailsがVueに吐き出す (あまり内容には触れないようにと言われているのでこんな感じです。)

Pythonつかったのは内部的に言語処理使いたかったので異論なくPythonでやろう!って感じな流れでした。 あとメンバーPythonかける人がいたから(助かった。w)

はい。というようなこと( 振り出しに戻る )をしていて、2日目は実装せずに内部構成だけ考ええて終わり。 (いや、残り半日なのにのんびりしすぎでは。。。)

この後に夜中にPythonAPIを作ってくれたKくん。プレゼン資料を作ってくれたYくんありがとう。。。 そんな中僕はVueのドキュメントをみていましたよ。。。。 (tsurai..)

余談ですが 3日目に必死に作りましたw 頑張った。うまく動いた!満足!!

機能実装に時間を裂きすぎてプレゼンがおろそかになってしまったのだけはすごい悔しいです。 後半の評価があと一つたかかったら3位になれたらしい?。。。辛い。。。笑 3位以上のチームには賞◯が贈られていたので....

懇親会とLT

  • 懇親会は美味しい食事とお酒がでました!!! (^^)/b
  • LT会は有志の学生と社員数名で行われました

開発が終わって肩の荷がおりたあとだったので色々なお話しを聞かせていただいたり。 LTはLinux、AIスピーカ、Netlifyなどなど面白い技術 (?) などなど、他にもたくさんの話があり,多種多様で面白かったです。


私事ですが、三日間の活動を評価していただき、 AteamさんのSenbatsuインターンシップの本戦へ行かせていただける挑戦権をいただきました。!!! 一ヶ月かけてサービスのビジネスモデルを作るようです。 今回入賞を逃してしまったのですが、次があるということで、次こそ優勝をもぎ取るためにがんばりたいなと思います

何を学べたの


端的に言うと。自分のエンジニアに対しての考え方が変わったな。と思っています。

(たったの3日で変わるわけないやん)

たった3日、されど3日。すごい濃厚な3日間でした笑。 (辛い時もありましたが、) それをこえて自分たちが検討していた機能を限られた時間の中で実装までこぎつけた時の 達成感 は言葉に表せないですね。

今までは要件に対して機能を作るこをするのが 'エンジニア' として考える部分が大きかったのですが

それ以上に

  • 実際にユーザに届け(デプロイするのはエンジニア)
  • ユーザに喜んでもらう (エゴサするのもエンジニアwww)
  • そして改善を加える (どんどん改善する PDCA!

ということが重要であり、エンジニアの役割 ということを改めて考える機会になりました。

その上で、実際にエンジニアとしてプロダクトを改善するにあたって。重要なことを学べました。

なぜユーザは不満を持っているのか。
新規(追加)機能の要望をあげているユーザは何に対して不満を持っているのか。
既存の機能が使いにくい背景はどんなことに依存しているのか。
ユーザがこのサービスを使っている理由はなんなのか?
そのサービスを使ってユーザはどんなことを実現したいのか?
どんな方法(機能追加・改善)をもってアプローチするのか?
その機能の将来設計はどうなのか?
本当にユーザが欲しているのか。

などなどこれ以上にもあると思うのですが、僕が印象に残っているのは以上のような観点でした。

また、チーム開発の際のお互いの役割などにも気付かされた気がしています。

各々で作業をするのも当然大事なのですが、それ以上にチーム同士での連携。助け合いなどがすごい大事だなと思いました。 そう行った点では、限られた時間の中で役割分担をしつつ各々の得意分野を生かす。ということができたのではないかと思います。

個人開発では絶対に気づけないことを容赦なく指摘し、僕らに成長の機会を提供してくださった、担当のkさん、fさんには感謝しきれないなと思っています。

他にもランチや懇親会でお話しさせていただいた全ての方に感謝を伝えたいです。

ありがとうございました!

今後どうしたいの


自分は今、将来の自分について考え始めたばかりで数年後の自分がどうなっているのか。というのをまだ具体化できていません。

ただ、今回のインターンを通じて

  • どんなエンジニアになりたいのか
  • エンジニアリングってどんなことする人なのか
  • 僕にとって本当に働きたい環境ってどんな場所なのか

このようなことを考えるきっかけになりました。

とくに最後の一つは大きく考えさせられ

  • 自分がどんなサービスにコミットしていきたいのか。
  • それってサービスにコミットできたらいいのか。
  • 周りの人との喜びの共有とか。働く職場の雰囲気とか、なんなら職場の立地とか。あらゆる側面での働きたい環境とはなんなのか。

思い返すと、いままで考えたことがなかったな。というのが本音です。

夏休みという長い (?) 時間があるので

  • 自分の将来について考えていきたいなと思いました。
  • もっと 技術に貪欲になろう 。(周りがすごかった。)

p.s. 長くなってしまいましたがエイチームのエンジニアサマーインターンシップはとても楽しい経験だったと思います。来年興味のある人がこの記事をみて’よし行くぞ!’となってたら僕はとても嬉しい。w

railsで検索するならRansack!!!!!!!!!!!!

ransack を使ったときになぜか検索できなかった話

最近の悩みだったんですよ ()

Railsの検索フォームを作る時ってさりげなくめんどくさくないですか。

めんどくさいですよね;;... めんd .... ゲホゲホ (異論は認める)

+ = form_tag xxx_yyyy_search_path do
+   .row
+     .form-group.col-sm-2
+       = text_field_tag :xxx_name,
+       { placeholder: "xxx", class: "form-control input-sm" }
+     .form-group.col-sm-2
+       = text_field_tag :yyy_name,
+       { placeholder: "yyy", class: "form-control input-sm" }
+      .form-group.col-sm-2
+        = submit_tag '検索するよー', class: 'btn btn-default btn-sm'
+def search 
+  @samples = Sample.page(params[:page]).per(PER)
+  if params[:xxx_name].present?
+    @sample = @sample.joins(zzz: :xxx)
+                     .where('xxx.name like ?', "%#{params[:xxx_name]}%")
+  end
+
+  if params[:yyy_name].present?
+    @sample = @sample.where('name like ?', "%#{params[:name]}%") 
+  end
+  
+  @sample = @sample.decorate
+end

これ。死ぬほど冗長だし、ちょっと(どころじゃなく)見栄えが悪いんですよね。 検索したいcolumnがふえるたびにViewに

+ .form-group.col-sm-2
+   = text_field_tag :new_column,
+   { placeholder: "検索したいcolumnふえたよ!", class: "form-control input-sm" }

↑のようなViewを追加し、

+  if params[:new_column].present?
+    @sample = @sample.where('new_column like ?', "%#{params[:new_column]}%") 
+  end

のように追加しないといけないんですよ。 DBがふくらんで3個どころじゃなく検索したくなったらどうするつもりですか?????? (心の声:頑張る) ←やめてください

そんな時に使うのが Ransack というGemです (https://github.com/activerecord-hackery/ransack

これがとても素晴らしいもので、早い、すごい、便利の三拍子を揃えているのです!

と、いうわけで

ransackの紹介と導入について

簡単に...(きになる方は本家みてw)

ransackは...README.

Ransack enables the creation of both simple and advanced search forms for your Ruby on Rails application (demo source code here). 
If you're looking for something that simplifies query generation at the model or controller layer,
you're probably not looking for Ransack (or MetaSearch, for that matter). Try Squeel instead.

だそうです。まあつまり シンプルだけど高度な検索をしたいならコレ!というわけです。 (雑)

ransackを使うためには

gem 'ransack'

もしくは

gem 'ransack', github: 'activerecord-hackery/ransack' # if you would like to use lates updates, use the master branch

をGemfileに記載し $ bundleするだけでじゅんびは終わりです。

def index
  @q = Person.ransack(params[:q])
  @people = @q.result(distinct: true)
end
<%= search_form_for @q do |f| %>

  # Search if the name field contains...
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont %>

  # Search if an associated articles.title starts with...
  <%= f.label :articles_title_start %>
  <%= f.search_field :articles_title_start %>

  # Attributes may be chained. Search multiple attributes for one value...
  <%= f.label :name_or_description_or_email_or_articles_title_cont %>
  <%= f.search_field :name_or_description_or_email_or_articles_title_cont %>

  <%= f.submit %>
<% end %>

とすれば良いみたいです。個人プロジェクトに入れたのだいぶ昔でサンプルないので公式をコピペ。

search_form_for

というのがRansackが提供しているメソッドでRansackを使う検索をする場合はForm_forではなくこれを利用します。
  上記のような記載にしてあげることでRansack様の恩恵を受けられます。   またransackを利用するさいにはsearch_filedへ引数を利用することで検索条件を変更することが可能です。

上記のような、

<%= f.search_field :name_cont %>
<%= f.search_field :articles_title_start %>

という場合は name columnに対してLike検索、 関連先の、articlesのtitleに対してのlike検索。を行います。 (多分 has_many articlesの関係)

  その他にも、https://github.com/activerecord-hackery/ransack

シンボル引数 内部条件
column_eq 完全一致
column_matches like検索
column_cont 部分一致
column_true bool検索
column_blank blankかどうか
column_present 存在確認
column_null null確認
not column_not_eq みたいに否定ができる

などなどあります。 自分は公式のドキュメントや、

http://nekorails.hatenablog.com/entry/2017/05/31/173925

↑のサイトをみたりしてます。


そんな便利なRansackさんですが、

セキュリティ的なことを考えると機能によってはチューニングしないといけないのです。

今回自分はそれに気づくまで時間をとかしてしまったので、猛省しながら本記事を書こうと思ったわけです。

ちなみに今回僕が遭遇したのは、

特定のcolumnでは検索できるのに 他のcolumnでは検索ができない。

まずは遭遇したエラー文ですが↓

 undefined method `xxx_cont' for Ransack::Search<class: Entry, base: Grouping <combinator: and>>:Ransack::Search

うーん、エラー文としてはよくあるアレですよね、
Nomethod error ........ ウルセェ!モデルに columnあるだろ!!!! f●ck!!!!!!!!!!

ただ、この時もControllerにて

def action
  @q = Model.search(params[:q])
  @instance_valiables = @q.result
end

のようにしてたわけで、この @q の内容は

=> Ransack::Search<class: Model, base: Grouping <combinator: and>>

になっており、正常にRansackのメソッドになってるんですよね。うーん。

RailsContsoleで

Model.ransack({xxx_cont: 'sample'}).result

→と、すれば該当モデルの'xxx'カラムに対して検索もしてくれてる風なレスポンスですしお寿司。。。 (今思えば、実際は検索されていないで Model.allの結果になってたっぽい気がする)

↑↑↑↑↑↑

とまぁ。状況の創造はできたと思うので実際の対処になります。

該当columnで検索してないのに絞り込めてない時の対処が以下になります。

問題としては該当モデルのファイルにて

self.ransackable_attributes self.ransackable_associations

ransackのオーヴァーライドが原因になっていました。 自分が作業をしていた時は

  def self.ransackable_attributes(*)
    %w[created_at]
  end

  def self.ransackable_associations(*)
    %w[]
  end

となっており、検索したい name columnが検索対象の columnとして登録がされておらず。 また、関連先の定義がされていなかったため、articleに対する検索すらもできなかったということになります。。。。。。。。。。。。。。。。。。

つらい。 しんどぃ。。

なので、以下のメソッドに変更を加え、

  def self.ransackable_attributes(*)
    %w[created_at name]
  end

  def self.ransackable_associations(*)
    %w[articles]
  end

のようにすると name columnでも検索が可能になりますし、articleへの探索も可能になるのです。

これで動くのでひとあんしんですね。

余談

まぁなんというか、エラーでて調べてもこの手のエラーへの対処がなかったので今回書いてみたんですが。 行ってしまえば、自明な内容になってしまいそうなので、今回はさらに一歩踏み込んだ内容について考えてみようかなと。

ransackのsource codeをのぞいてみよう。。。!

初めてOSS?をコード見るためにCloneしました。
はるか昔にDevise(認証用のGem)をみたことがあるが黒魔術すぎて3秒で諦めたなぁと物思いに老けながらgit clonne...)

今回の諸悪の根源である該当メソッドは以下のファイルにて定義されています。 (https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/adapters/active_record/base.rb)

 # Ransackable_attributes, by default, returns all column names
 # and any defined ransackers as an array of strings.
 # For overriding with a whitelist array of strings.
 #
 def ransackable_attributes(auth_object = nil)
    @ransackable_attributes ||= if Ransack::SUPPORTS_ATTRIBUTE_ALIAS
      column_names + _ransackers.keys + _ransack_aliases.keys +
      attribute_aliases.keys
    else
      column_names + _ransackers.keys + _ransack_aliases.keys
    end
 end

 # Ransackable_associations, by default, returns the names
 # of all associations as an array of strings.
 # For overriding with a whitelist array of strings.
 #
 def ransackable_associations(auth_object = nil)
   @ransackable_associations ||= reflect_on_all_associations.map { |a| a.name.to_s }
 end

がっつりコメントアウトされとるやんけ!!!!!!!!

# Ransackable_attributes, by default, returns all column names # and any defined ransackers as an array of strings. # For overriding with a whitelist array of strings. # ちょっとした時に使う分には全ての columnにたいしての検索でもいい。ということからデフォルトは全ての columnをreutrnしている。

しかしながら、悪意のあるユーザにとってはこれがSQLインジェクションの入り口になったり? インジェクションはできなくても製作者が意図してない検索をさせることも容易に想像ができます。

そのため今回のプロジェクトでは該当メソッドをオーバーライドして検索をかける場合は自分が許可したものしか通さないんですね。 うーんStrongParameterに似ている気がするw

ちなみに改めてREADMEをみていると

Authorization (whitelisting/blacklisting)

ちゃんと記載してありました。Document読みましょう。

まとめ。

documentを読みましょう。答えはそこにある。。

とりあえずRubyが動くまでの環境構築メモ

必要なもの

  • エディタ
  • HomeBrew(以下の管理のため)
    • rbenv(rubyを管理する)
    • mysql(今回は5.7入れたい)

エディタ(高機能なメモ帳)

以下のうちどれか一つ。オススメ順

HomeBrew

以下ターミナルでの操作

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

時間かかる -> おわったら

 brew doctor

→ command not foundじゃなければおk

変なwarningがでていたら → https://qiita.com/unsoluble_sugar/items/acaffa6d0e28c3c24934 頑張れそうなら解決してみて

rbenv(rubyを管理する)

brew install rbenv ruby-build

-> rbenv --version

→ command not foundじゃなければおk

echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

source ~/.bash_profile

(変化なくて問題ない)

ruby の 2.5.0を入れる

rbenv install 2.5.0

rbenv versions

-> 2.5.0があればおk

rbenv global 2.5.0

rbenv rehash

ruby -v

-> 2.5.0ならおk

mysql

brew install mysql@5.7

brew link mysql@5.7

mysql --version

-> Command not Foundじゃなければ なんかワーニングでてたらそれ打てばおk

MySQLを立ち上げるには、
次のように入力して、エンターキーを押します。

$ mysql.server start

MySQLを終了するには、
次のように入力して、エンターキーを押します。

$ mysql.server stop

サーバにインストールしたMySQLは、常時起動するようにするのですが、
ローカル環境でMySQLの学習以外の作業もすると思いますので、
MySQLは、使う時に立ち上げて、使い終わったら、停止しておくのが良いと思います。
再起動はこれ。
$ mysql.server restart

MySQL のステータス確認
次のように入力して、エンターキーを押します。

$ mysql.server status
起動している場合はこのように表示されます。
SUCCESS! MySQL running (13035)

停止している場合はこのように表示されます。
ERROR! MySQL is not running

command not foundは基本的にNGなのでその時はがんばること。