20211201のRubyに関する記事は9件です。

【IT業界未経験】テックキャンプからエンジニア職に就職するまでの記録

はじめに 2021年3月から学習を始めて内定をもらうまでの記録をまとめました。 参考にして頂けれる所とこれは参考にならないなど反面教師にして頂ければ幸いです。 章 内容 簡単な経歴 自己紹介 学習から内定までの道のり 時系列にまとめています 転職活動内容 実績と面接等について テックキャンプについて テックキャンプでの学習について詳細を詳しくまとめます やって良かった事 面接で評価された事など 自己紹介 2018.3 文系大学卒業(観光学を専攻) 2018.4 新卒で旅行会社の営業職として入社 都内の小中高学校の修学旅行などの提案や添乗業務を行いました 2021.3 テックキャンプ丸の内校98期として入学 2021.3 退職(3月の上旬に退職し、残りは有給消化のため) 学習から内定までの道のり 2021年3月22日 テックキャンプ98期として入学。同期が7人いて毎日アウトプットしながら学習開始。 会社は3月31日まで在籍しておりましたが、有休消化のため3月19日で出勤終了。 2021年4月〜5月22日 少しづつ他の同期から遅れをとり始めて焦りながらも学習をし、無事卒業。 (内容についてはテックキャンプについての章で詳しく書かせて頂きます。) 2021年5月23日〜6月 卒業後も学習を続けオリジナルアプリに取り掛かりました。 しかしHTML・CSSがうまくできず苦戦。もう一度Progeteで復習し、同期から教えてもらったUdemyの教材で復習。 ここに時間をかけ過ぎました。簡単に復習すれば良いもののしっかりと時間をかけてしまい同期との差が生まれました。 下旬頃からは渋谷校の98期の同期とも交流をし始め、毎日アウトプットの会が開かれました。 2021年7月〜8月 ようやくオリジナルアプリに取り掛かりました。フロントに時間をかけるのはもったいないと気づき、Bootstrap・Font Awesomeを取り入れていきました。 下旬頃に父親が体調を崩し入院し看病できるのが私しかいなかったので8月中旬頃までは学習を中断する状態となりました。 就活も中断する事になるのでカリキュラムも見れなくなりました。 2021年9月 アプリが完成し始め、AWSへ1から構築しデプロイするのに3週間かかりました。 まずはAWSの学習をUdemyで行い、Qiitaの良き記事を参考に作成。 同期が次々と転職する中で焦りに感じ、dockerなどを導入を考えていたのですが、諦めてりあえずデプロイして就活を始める考えになりました。 2021年10月 デプロイができたが、Capistranoは導入したと思い、導入するが度重なるエラーによって涙目。 1週間自分で考えたが解決できずにここで始めてMENTAを使いました。 教えてもらってはエラーとなりの繰り返しで導入まで3週間かかりました。 ここが一番地獄だったかもしれません。 4週目頃にようやく完成しました。 2021年11月 やっと自ら応募し始めました。 使った媒体はWantedlyとテックキャンプ経由の2つから応募しました。 履歴書・職務経歴書はすでに完成しており、面接練習も学習しながらやってきたのですぐに就活フェイズに移る事ができました。 毎週2・3社面談をして4週目に2社内定が出ました。 転職活動内容 オリジナルアプリが完成する前の実績 2021.6〜8月までの実績 応募媒体名 応募企業数 書類通過数 内定 テックキャンプ経由 5 0 0  理由 結論から言うとこの頃はやる気が転職する気がありませんでした。 オリジナルアプリが完成していない人材に内定を出す企業なんてない!内定を出すとしたら怪しいと勝手に思い込んでいました。 「じゃあなんで応募するんだよ!」と言うとテックキャンプの卒業後、カリキュラムを見たければ週1社応募しなければいけませんでした。 就職活動の意思がないとカリキュラムを見る事ができないのでとりあえず的な感覚で毎週1社だけ送っていました。 完成後の活動内容 2021.11.1 〜 11.24 自分から応募を行ったのは11月からでした。 応募媒体名 応募企業数 書類通過数  カジュアル面談  1・2面接  最終面接   内定  テックキャンプ経由 4 2 2 2 1 0(2社内定のため辞退) wantedly(スカウト) 17 0(全て辞退) 0 0 0 0 wantedly(自己応募) 6 4 3(1社辞退) 3 2 2 テックキャンプについて 10週間のプログラムをこなす形になります。 10時〜20時までは必須で学習を行い、1時間事に学習した内容を同期とzoomを繋いでアウトプットする学習方法になります。 もし分からなければメンターさんに質問ができるので躓くことはありませんでした。 98期は7人いて平日5日間毎日顔を合わせていました。 1週目〜2週目半ば 基礎カリキュラムを終わらせました。 内容は・・・ HTML・CSSについての学習 簡単なLinuxコマンドについて Rubyの基礎文法 Railsの基礎について MVCなど理解が中々できずメンターさんに質問しまくりました。 また次の応用に行く前にテストがあり、合格しなければ応用カリキュラムに進むことはできません。 2週目半ば〜4週目 応用カリキュラムに入り、実際にアプリを作成する段階に入ります。 簡単な投稿系アプリの作成 git hubの使い方 テストコードの書き方 メッセージのやりとりができるアプリ作成 実際にアプリを作る事で理解が深まってきました。 5週目〜7週目半ば ここから発展カリキュラムに入ります。 Javascriptの基礎 Javascriptを使った簡単なアプリ herokuへデプロイ 簡単な投稿系アプリを実践的に作成 実践的にアプリを作成するため、ヒントしだけもらって自分で開発していく形になります。 投稿機能ができたらメンターに報告し、できたら次の機能の開発へ進んでいきます。 ここで同期と差ができていき、土日もフルで学習しました。 ここでも分からなかったら質問ができます。 7週目半ば〜9週目半ば 最終課題に突入です。 フリマアプリの作成をヒントなしでの開発です。 基礎や応用のカリキュラムを復習しながら開発しました。 やり方は発展カリキュラムと同じやり方で機能別でメンターに報告していきます。 最終的には7人中4番目に完成しました。 9週目半ば〜10週目 ここからはオリジナルアプリの構想と設計をし始めました。 メンターさんには聞く事はできないので分からなければ自分で解決するしかありません。 カリキュラムを参照しながら進めました。 同期の中ではすでにオリジナルアプリを完成する人もいました。 よかった所 メンター 質問し放題なので毎日10回程度は質問してました。 私の場合はほとんど答えて下さったので嫌な印象はなく大満足でした。 ライフコーチ 期ごとにライフコーチが一人つきます。 毎週1回面談があったので悩み事やカリキュラムの進みについて相談に乗ってくれました。私は教室で学習する事が多く、教室にはライフコーチの方がいらっしゃったので直接相談することもできました。 キャリアアドバイザー 就活について相談ができるアドバイザーが一人つきます。 履歴書・職務経歴書や面接対策などアドバイスをくれます。 就職するまで担当者が1回変わりましたが特に問題はありませんでした。 強いて言うなら最初のCAさんはオリジナルアプリに時間かけないで早く就活しましょうと圧がすごかったのです(笑) またオリジナルアプリができてないからかテックキャンプ経由でくる求人は全てSESでした。 逆に完成してからは全て自社・受託系の企業でした。 興味がある会社もたくさん紹介してくれたので不満はあリませんでした。 丁寧に添削してくれるのでとてもよかったです。 同期 同期とは卒業後も毎日情報交換zoomをしてました。途中からは渋谷校の同期の方とも一緒にzoomしました。 徐々に就職が決まり減っていきましたがチャンネルには残って下さったので、転職後のお話なども聞くことができました。 一緒にエラーを解決してるれる同期や自走力の塊の同期がいたり、参考になる方ばかりでこの方々がいなければ途中で諦めてたかもしれません。 やって良かった事 Qiita アウトプットのためにQiitaを毎日投稿してました。 途中からは毎日投稿ができなくなったのですが、なるべく投稿することを心がけました。 投稿することによって学習の定着につながりました。 一番は面接時の話の種になります! 投稿することによって自走力にも繋がり、どの企業に面接に行っても必ず評価して下さりました。 寿司打 テックキャンプ入学から毎日欠かさず寿司打を続けました。 最初はブラインドタッチなんてできなかったのですが、今では余裕です(笑) 一万円コースも5,000円プラスで毎秒5.4秒にする事ができました。 Wantedlyスコアを上げる 転職サイトはWantedlyを利用しました。 できるだけ自分の情報を載せて知ってもらうためにめちゃくちゃ書きました。 最初はスコア40程度だったのですが細かくできるだけ書き、最終的にはスコア89になりました。 上がれば上がるほどスカウトがきた印象です。 オリジナルアプリ これは確実に必要です。 何か問題解決できるサービスか自分が必要だなと思ったサービスを作れば自ずと作成意欲も湧いてきますし、面接で説明を求められた時に丁寧に答える事ができます。 私の場合は教育旅行系の投稿アプリを作成しましたが、AWSの1から構築したくらいです。 本当はdockerやCircleCIなどは導入したかったですが、AWSに手こずったせいでできませんでした。 自社開発系の企業の面接の場合はオリジナルアプリについて聞かれる事はありましたが、SES系企業の場合は聞かれる事はありませんでした。 スライド作成 これは同期が転職の際に作成していて参考にして作成しました。 なぜこのアプリを作成したのか?、市場分析してグラフなどを用いて根拠を説明するスライドになります。 READMEに説明書くからいらなくねと思う人もいるかと思いますが、就活でかなり有効でした。 スライドを見てくれてWantedlyのスカウトをしてくれた企業や面接前に見てくれて、市場分析までして作った人はあまりいないと評価をしてれました。 最後に 同期の中でも脱落していく人はいました。 しかしどんなに長くなっても諦めなければ必ず転職できる思います! 実際に私がそうでしたし、周りの同期を見てもそうでした。 他の記事でも皆さんおっしゃってましたがただテックキャンプに入れば転職できると思ってる人は厳しいかと思います。 参考にした記事 めちゃくちゃ尊敬する方の記事です
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【RSpec】JSONの値を確認するテスト

環境 Ruby 3.0.2 Rails 6.1.4.1 APIのリクエストテスト gemを使わずにjsonが期待通りに取れているかのテストを書くとこうなる。 describe "GET /api/v1/fruits" do subject { get '/api/v1/fruits', headers: headers } let!(:available_fruits1) { create(:fruit) } let!(:available_fruits2) { create(:fruit) } let!(:unavailable_fruits) { create(:fruit, :unavailable) } it '旬の果物を返すこと' do subject json = JSON.parse(response.body) expect(response.status).to eq 200 # 果物が3つあり、そのうち旬の果物が2つ、旬じゃないのが1つ。jsonで取れるのは果物が2つ expect(json['fruits'].length).to eq 2 # 旬の果物の2つは含まれているか expect(json['fruits'][0]).to include({"id"=>available_fruits1.id}) expect(json['fruits'][1]).to include({"id"=>available_fruits2.id}) # 旬でない果物は含まれていないか expect(json['fruits'][0]).not_to include({"id"=>unavailable_fruits.id}) expect(json['fruits'][1]).not_to include({"id"=>unavailable_fruits.id}) end end 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

micro:bitをRubyでブラウザだけでプログラミングするプログラミング環境「rbCanvas」の紹介

この記事は「micro:bit Advent Calendar 2021 - Qiita」の2日目の記事です。 rbCanvas https://rbcanvas.net/ (rbCanvas公式ページ より) 1. はじめに micro:bitを使えるプログラミング言語としては、今までブロック(MakeCode、Scratch3、Smalruby3)、JavaScript(MakeCode)、Python(MakeCode、MicroPython)C/ C++、Swift(Swift Playgrounds)などがありました。 そこに、昨年の公開された「rbbit」でRubyが加わりましたが、今回大幅にパワーアップして「rbCanvas」になりました。 rbCanvasのブラウザだけで完結するRubyプログラミング環境によって、ブロックによるプログラミングから、テキストによるプログラミングに比較的簡単にステップアップできます。 また、Ruby on Railsなどで幅広く使われているRubyの初心者向けの学習ツールとして、micro:bitを使うことはとても有効だと考えています。 2. rbCanvas とは Rubyでmicro:bitを使えるようにするブラウザベースのプログラミング用ツールです。 特徴 ブラウザとインターネット環境だけで動作 パソコンにインストール不要(Rubyのインストールも不要) 無線(Bluetooth)接続 エディタ付属 2Dゲームライブラリ付属(DXRuby相当) 仕組みとしては、micro:bitとパソコン(PC)をBluetoothで接続し、お互い無線通信することでPCからmicro:bitに制御命令を送ったり、micro:bitからセンサーなどの情報をPCに送ることで、お互いのやりとりを可能にします。 これは、MakeCodeのようにmicro:bitにプログラムを転送して実行させる方式ではなく、Scratchで実行時にコマンドをScratch Linkによって送受信するイメージに近いです。 3. できること 対応 LEDの点灯(階調表示可)、消灯、文字の表示 スピーカー出力 センサーの値の取得(加速度、傾き、明るさ、温度)、およびブラウザでの表示 ボタン、タッチセンサーの状態の取得 Bluetooth無線通信 未対応 磁気センサー P0など入出力端子 マイク 現状でも、micro:bitのほとんどの機能が使えるようになっています。 その他 2Dゲームライブラリ(DXRuby相当)との併用可(ブラウザ上) ユーザインターフェース(UI)用のパーツとの併用可(ブラウザ上) マウス、キーボードによる入力取得可 4. 参考サイト rbCanvas公式ページ 5. 動作環境 A. 対応PC OS Windows macOS Linux ※ BLE(Bluetooth Low Energy)に対応したBluetooth 4.0以上が必要 ※ Rubyのインストール不要 B. 対応ブラウザ Google Chrome(Web Bluetooth機能必須) C. 対応micro:bit micro:bit v2 のみ (micro:bitには、専用プログラムを書き込んで使用) D. 接続 Bluetoothによる無線接続 (BLE(Bluetooth Low Energy)対応 Bluetooth 4.0) ※ 最初に専用プログラムを書き込むためにUSBケーブル接続が必要 6. 準備 micro:bitへ専用プログラムの書き込み micro:bitを使う前の準備 を見ながら実行します。 micro:bitに、rbCanva用のBluetooth通信を解釈する専用プログラムをあらかじめ書き込みます。 1) rbCanvasのページ から、専用プログラムをPCにダウンロードします。 2) ダウンロードしたプログラムをmicro:bitに書き込みます。(ここのみUSBケーブル接続) 3) micro:bitのLEDが以下のように点灯すると、正しく書き込めています。 (rbCanvas公式ページ より) 7. rbCanvasを使ってみる A) サンプルプログラムの実行 A-1) rbCanvas のサンプルプログラムのページを開きます。 A-2) 実行させたいサンプルのサムネイル(画像)かタイトルをクリックします。 A-3) micro:bitとBluetooth接続をするためのウィンドウが開きます。 A-4) 「選択」を押すと、micro:bitとペアリングするパネルが開きます。 ※ パネルが開かない場合は、ブラウザのキャッシュを削除して、ブラウザを再起動するといいようです。 A-5) プログラムが実行されます。 B) エディタを使ったプログラムの作成と実行 B-1) rbCanvas のページの「rbCanvas editor」をクリックします。 B-2) rbCanvas editor のウィンドウが開きます。 ※ あらかじめ記入されているプログラムは、micro:bitでは使わないので全て削除して構いません。 B-3) プログラムを書く ・サンプルプログラム「ハートの点滅」 mb = Microbit.new heart = [ '01010', '11111', '11111', '01110', '00100' ] mb.connect do i = 0 while i < 5 mb.led_show(heart) sleep 0.5 mb.led_off sleep 0.5 i += 1 end end ちなみに、サンプルプログラムのタイトルをエディタウィンドウにドラッグすると、エディタにコードが読み込まれてプログラムが編集できるようになります。 B-4) 実行は、エディタ上部の「▶︎ ボタン」を押します。 実行すると、ハートが5回点滅します。 文法、プログラム例は マニュアル>APIリファレンス>Microbitクラス で見ることができます。 C) プログラムの保存 エディタ上部のダウンロードボタンを押します。 8. 困ったときは 公式ページ>マニュアル>よくある質問 が用意されています。 よくある質問 9. さいごに micro:bitをRubyからも扱えるようになり、micro:bitの魅力が一段と増しました。Rubyによるmicro:bitプログラミングは、小学校高学年から中学、高校、大学などでも、プログラミング教育に十分活用できる可能性があると思います。 rbCanvasによって、とても手軽にRubyのプログラミングが始められるようになりました。ぜひ試してみてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitサーバーが搭載された楽譜共有WEBサービスを作成した

楽譜共有WEBサービスを作成した 概要 「楽譜を共有する」サービスを作った。 既存サービスと異なる点 基本的にコードで楽譜を記述する Gitサーバーが搭載されているので、楽譜の間違いなどを修正することが容易 アーティスト情報や曲情報を整理できるようになっている 例) 「凛として時雨」「TK from 凛として時雨」「Ling tosite Sigure」どれ...? 翻訳機能がついている それを作るにあたって、困ったこと、工夫した点、使用した技術、などをまとめたいと思います。 ※語彙力ないです alphaTab様の恩恵が非常に大きいです 自己紹介 大学3年生 都内在住 WEBエンジニア はじめまして。私は主にWEB系の開発を行っています。 プログラミングは大学1年生の時にRailsTutorialに入門しました。 今は、RailsとReactをメインで開発を行っています。 今回使用した技術 STAVE Editor STAVE Editor 概要 STAVE Editorとは、楽譜を記述するデスクトップアプリケーション シンプルに記述が可能なalphaTexを採用 Javascriptで記述することが可能 Git管理が可能 STAVE Editor 技術 STAVE Editor 工夫 alphaTab様が提供しているalphaTexをJavascriptで動くようにした。 Node.jsとElectronとReactをうまく組み合わせた UIでGitを扱える STAVE Editor 展望 alphaTexのLint機能 UIのアップデート STAVE Web STAVE Web 概要 STAVE Webとは、alphaTexの楽譜を共有、表示するWEBアプリケーションです。 Git Serverを搭載 alphaTexを表示、再生が可能 曲、アルバム、アーティスト、バンドなどの情報を整理することが可能 STAVE Web 技術 Git Serverを備えていて、pushするとNginxとRails(devise)でBasic認証を行うようになっています。 STAVE Web 工夫 NginxとRailsのdeviseを組み合わせてGit Push時にBasic認証を行った GraphQL使ってみた。 既存の楽譜アップロードサイトと差異をつけるために、曲情報、アーティスト情報、バンド情報を正しく整理できる設計になっている。 STAVE Web 展望 ブラウザでSTAVE Editorを使えるようにする。(JSでJSスクリプトの実行さえできればいける) UIのアップデート alphaTex以外もアップロードできるようにする git push時に拡張子をチェックし、不適切なファイルは取り除く gitファイルを外部のストレージサービスに保存する CI/CD 技術話 React + Typescript + VSCodeはすごい メリット ほかのJSフレームワークに比べて型が効いてる(気がする) Vue(3は知らん)やAngularに比べて、型がよく効く JSXの属性に渡す値などもReactは厳密にチェックしてくれる デメリット JSファイルにCSSファイルをインポートして要素に適応させるのは面倒くさい Typescriptに対応していないパッケージを使用する際に、既存の型システムに適応させながら組み込むのがめんどくさい React Component + Typescript Genericsすごい 場合によりますが、とにかくすごいです。コンポーネントを様々なデータ型で使いまわしたい場合最強になります JSのオプショナル演算子はとりあえず使えばいいわけではない Typescriptの「undefineやnullを含む可能性がある」という警告に対して、とりあえずオプショナル演算子をつけるのはあまりよくないという話です。 特に、GraphQLやエンドポイントの多いREST、JSフレームワークのコンポーネントがpropsのバケツリレーを多くする場合に非常に重要になります。 GraphQL + devise_token_authの組み合わせをどうにかしたい 本来であれば、REST APIかGraphQLのどちらかの設計に寄せるべきです。 しかし、GraphsQLでヘッダーの称号や認証を行うスマートな方法が思いつきませんでした。 結局、認証のいらないリクエストはGraphQL、認証のいるリクエストはRESTという構造になってしまい、気持ち悪くなってしまいました。 多言語対応した 今までの楽譜共有サービスでは、アーティストの記述の違いや、曲名の誤字、スペースの混入などが多く、検索をかける際に不便でした。 また、youtubeやspotify,itunes,wikipediaなどの、外部のサイトと連携を行う際に以下のような問題が起きました。 アーティスト名や曲名が国によって異なる wikipediaのurlが国によってことなる itunesでの曲タイトルが国によって異なる これらの問題を容易にに解決することができたのはmobilityのおかげです! GithubActions dispatch_event 便利 GithubActionsのdispatch_eventを使用してみました。 リポジトリが更新された場合、このリポジトリを所有する親リポジトリの参照を更新するものです。 わざわざ親リポジトリを開いて、下記のコマンドを実行するのはめんどくさかったので、よかったです git submodule update git add git commit git push 展望 実はStave Web/Editorだけではなく、Stave Effectorのプロトタイプも作成しています。これは、ブラウザのWEB Audio APIを使用して、ギターなどのエフェクターを仮想的に作るものです。こちらの開発もしたいと思っています。 個人的には、コードベースの楽譜データを貯めると、いろんなサービスに展開することができると考えています。 デベロッパー向けにAPI解放することで機械学習による作曲ができる カラオケサービス 楽器の学習サービス 作曲や楽器への学習 音楽業界の振興 ...etc デプロイしたのですが、それを公開するのはまだ早いと感じています。 著作権の問題を解決するための窓口のシステム開発や、UIのアップデートは必須です。 また、様々な音楽著作権団体と包括契約を行う必要があるでしょう。 なので、いつかデプロイできたらなーと考えています! ここまで読んでいただきありがとうございました! なにかありましたら、下記のTwitterから気軽にメッセージをください。 (就活してます) Twitter
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

細かいつまずいたことをメモしておく(11月編)

はじめに 11月の個人的につまったところのメモになります。 Qiitaに記事にするほどでもないかなというものを自分用にまとめています。 今月は大した作業はなく問題は少なかったです。 問題 1. なぜか子モデルが作成されず、モデル名_idがないと言われた class_room.build_member(number: row[:number]) rowはExcelのファイルをhash形式にした各行を表しています。 ここで、class_roomをsaveすると、member_idがないというSQLエラーが出ます。 原因は、row[:number]がinteger型で送られてくるのに対して、numberカラムのバリデーションでstringになっていたことからmemberの作成ができずに、(エラーは起きるが)class_roomが作成されるため、参照するmemberがないので怒られていた。 class_room.build_member(number: row[:number].to_s) とすることで解決した。 2. Rails/UniqueValidationWithoutIndex: Uniqueness validation should be with a unique index. Rubocopを走らせたところ以下のエラーが発生 Rails/UniqueValidationWithoutIndex: Uniqueness validation should be with a unique index. indexを張ったところ、このようなエラーが発生した。 staff_number.rb def up add_index :staff_number, :employee_code end def down remove_index :staff_number, :employee_code end インデックスをユニークにしてねと言われてるので、ユニークにしたがエラーは変わらず発生 staff_number.rb def up add_index :staff, :employee_code, unique: true end def down remove_index :staff, :employee_code end そこでエラーをよく確認すると validates :employee_code, presence: true, uniqueness: { scope: :staff } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ scopeのところで参照しているがそこにindexが張られていないことが原因であると気づいた。 そこで、stuff_numberとstuffモデルをつなぐ、stuff_idにindexを張る staff_number.rb def up add_index :staff, [:employee_code,:staff_id] unique: true end def down remove_index :staff, [:employee_code, :staff_id] end これでうまくいった。 2. フォームに入力をして登録でcreateをしたがリダイレクトされない form_withを使って、ユーザーを作成し成功するとログイン画面にredirectされるはずなのにリダイレクトされなかった。renderも効いていなかった。 form_withはlocal: trueオプションをつけないとAjaxになってしまい、HTMLがレンダリングされないのが原因だった。 Rails 5.1のform_withを使ってうまくredirectできないあなたへ 3. 再帰のRspecでテストに困った 以下のようなモデルのメソッドをテストします。 test.rb def unique_login_id login_id = SecureRandom.alphanumeric(6).downcase return login_id if User.find_by(login_id: login_id).blank? unique_login_id end ランダムな文字列をlogin_idにしてユーザーでそのログインIDを利用している人がいるかを検索 1. いなければlogin_idを返す 2. いた場合は再度unique_login_idを呼び出す ここで2のテストに躓きました test_spec.rb describe 'unique_login_id_assign' do subject(:result) { test.send(:unique_login_id) } let(:test) { create(:test) } let(:login_id) { 'test_id' } before do user = create(:user) user.login_id = login_id user.save end context '作成した共通IDがログインIDと重複しているとき' do it 'ユニークな共通IDを返すこと' do allow(SecureRandom).to receive(:alphanumeric).and_return(login_id) expect(result).to eq login_id end end この方法だとallowが常に同じものを返し続けるためループし続けてしまいます。 そこで以下の記事を発見しました。 rspec-mocksを使ってテストで上手に手を抜こう この記事によるとand_returnで複数の値を返せるようになるとのこと test2.rb user = User.new allow(user).to receive(:name).and_return('たろう', 'じろう', 'さぶろう') user.name # たろう user.name # じろう user.name # さぶろう user.name # さぶろう これをうまく利用することでテストがかけました。 test_spec.rb describe 'unique_login_id_assign' do subject(:result) { test.send(:unique_login_id) } let(:test) { create(:test) } let(:login_id) { 'test_id' } before do user = create(:user) user.login_id = login_id user.save end context '作成した共通IDがログインIDと重複しているとき' do it 'ユニークな共通IDを返すこと' do allow(SecureRandom).to receive(:alphanumeric).and_return(login_id, 'unique_login_id') expect(result).to eq login_id end end ちなみにモデルSpecのプライベートメソッドはsendを使うことで呼び出せます RSpecでprivate(プライベート)メソッドをテストする[Ruby][Rails] 4. パラメータを付与したときにエラーになって処理が始まらない URLにauth_tokenというパラメータを付与して、アクセスする処理を行っていたのですが、なぜかエラーが発生してしまう。 before_actionも動いていないようだった。 ActionController::BadRequest: Invalid request parameters: Invalid encoding for parameter: rails Shift_JISの日本語パラメータを受け取る 調べたところ400 Bad requestが原因だった。 これはブラウザに起因するもので、URLのエンコードが正しくない場合に起こるそうです。 試しにlocalhost:3000?auth_token=testなどでアクセスしたら問題なく動いた 400はブラウザの関係もあるため、このままにすることにした おわりに 技術的に挑戦ができていなかった月となりました。 やはり出社になったり、忘年会準備だったりと勉強の時間が少なかったのが原因かなと思いました。 来月はAWSの勉強に挑戦していきたいです。 参考 Rails 5.1のform_withを使ってうまくredirectできないあなたへ rspec-mocksを使ってテストで上手に手を抜こう RSpecでprivate(プライベート)メソッドをテストする[Ruby][Rails] rails Shift_JISの日本語パラメータを受け取る
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

レガシーシステムからの脱却

前書き 昨年に引き続き、今年もKITのアドカレの記事を書いていきます。 ……他に話すべきこともないので早速初めましょうか。 レガシーシステムの闇 私がアサインされたプロジェクトではRailsでWebアプリを開発していました。最初のリリースが行われたのは5年前だったため、古いプロジェクトではありませんでした。 また、実際にそのアプリが動いているサイトにアクセスしてみたりもしましたが、怪しい様子はありませんでした……あくまでユーザ側から見れば…。 あるとき闇に気付く 環境構築をしていたとき、異変に気付きます。 CIが数年前から失敗してるけど、設定ミスかな 今使ってるRubyが数年前からEOFになってる… 更新されないGemfile テストどこ…? slimファイルでごり押しされたレイアウト ここから開発チームの戦いが始まりました。 1. CIが何年も前から失敗している CIツールのバージョンが更新されていないのが原因でした。 イシューは立っていたものの、誰もその問題に対処していませんでした。 2. Rubyのバージョンが古い Ruby 2.3が使われていました。EOFを過ぎているどころの騒ぎではないですね。 「ときどき警告が出るけど、アプリ自体は動くし大丈夫だろう」 という安直な考えの基に開発されてきた歴史が垣間見えました。 3. 全てのGemのバージョンが古い 「bundle updateしなければRubyのバージョンが古くても動くじゃん。じゃあGemも放置しとこう。」 4. テスト用のコードが少ない 想定されているテストケースがここまで少なかったのは衝撃的でした。当然バグも頻発し、機能実装は遅れがちになっていました。 5. slimファイルで十重ネスト slimの構文は確かに簡潔ですが、その簡潔さを理由にしてむやみにネストを深くしていい訳ではありません。 残念ながら、過去のプロジェクトメンバーは可読性を無視してdivタグを増やしまくったようで、ネストが永遠と続きそうなプログラムが大量に生み出されてしまっていました。 どう対処したか モチベを維持しつつ作業したかったので、簡単に解決できそうなものから順に取り組むことにしました。 私の場合は具体的には、 CIのバージョンのアップデート slimをerbに変更する 不足しているテストケースを補完する Rubyのバージョンアップ Gemの全体的なバージョンアップ の順で進めました。 保守メンバーが少なかったこともあり半年近く掛かってしまいましたが、以前よりもはるかに安全で保守性の高いものに改善することができました。 再発防止策 今回はメンバーの協力もあり、何とかシステムを改修できましたが、数年後に同じような事態に陥らないようにしなければなりません。 この問題を二度と引き起こさないように、今後はソフトウェアをアップデートしたりテストを書いたりするだけの日を定期的に設けることで、機能実装だけでなくリファクタリングも行う習慣を付けようと考えています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者向け】MechanizeでJavaScriptの箇所を読み取れない

■環境 ・Windows10(64bit) ・Ruby 2.7.4 ・Rails 5.2.6 ・Mechanize 2.8.2 ■MechanizeでJavaScriptの箇所を読み取れない 状況 Railsアプリケーションでgem「Mechanize」を使用し、Webスクレイピングを行っている。 しかし、HTMLファイル内のJavaScriptの箇所だけ読み取れない(パースできない)。 原因 MechanizeはJavaScript未対応 対処1 MechanizeではなくSeleniumなどを使用 対処2 JavaScriptが行うはずの処理をRubyで置き換える。 ただし、そのためにはJavaScriptの内容を読み解く能力が必要。 対処3 HTMLファイル内のscriptタグを削除し、読み取り可能になるか試す。 例 # Mechanizeの初期設定を実行。Mechanizeクラスのオブジェクトを作成。 agent = Mechanize.new # 保持する履歴の最大数を指定。「0」だとリファラー周りで不都合があるが、大きいとメモリ容量を取るため、「2」辺りが妥当。 agent.max_history = 2 # HTTPリクエストのヘッダーにUser-Agentを設定。指定文言以外だとMechanizeの情報が送信されてしまうため注意。 agent.user_agent_alias = 'Windows Mozilla' # キャッシュに存在するページへの再アクセス時に更新チェックを行うかどうかを設定。true:変更が無ければキャッシュを再利用。 agent.conditional_requests = false # URLを取得 top_url = 'https://sample.co.jp/' # MechanizeにてURLからHTMLファイルを取得し、パースを阻害するJavascript関連のタグを削除。 html = agent.get(top_url).body.gsub!(/<script.*?>/, "").gsub!(/<\/script>/, "") # 以降で必要なパースなどを行う ・Mechanizeのgetメソッド: URLが表すページを取得する ・Mechanizeのbodyメソッド: ページのBody部を返す ・gsubメソッド: 文字列を置換する。標準では非破壊的メソッドのため、今回は「!」を付け破壊的メソッドにしている。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

文字列をランダムなストリームに変換する

与えられた文字列をバラバラにして、ランダムに並び替えて出力する Enumerator を返すメソッドというものを考えてみましょう、と思ったのですが… まずは、愚直に1文字ずつ取り出す仕方を考えると、文字列を配列に変換して、Array#delete_atを使うかなと。こんな感じ。 random_stream1.rb def random_stream1(str) tmp = str.chars Enumerator.new do |y| tmp.size.times do y << tmp.delete_at(rand(tmp.size)) end end end str = "Ruby is smart programming language!" stream1 = random_stream1(str) stream1.to_a.join #=>"rlg uin!yaR rsgansbae tugmmamrop ig" それよりも、便利メソッドArray#shuffleを使えば、もっと簡単か。せっかくストリームにしているので、改行コードがあったところで切ってみることにしましょう。 random_stream2.rb def random_stream2(str) str.chars.shuffle.to_enum end str = "Ruby is smart programming language!\n" stream2 = random_stream2(str) stream2.to_a.join #=>"gniaasanmoy\n grgietsla p mg!u umrbRr" stream2.take_while { _1 != "\n" }.join #=>"gniaasanmoy" でも、メモリ効率を考えて Enumerator を返しているのに、途中で配列に直しているのがどっちもいまいちって感じがするんですよねー… なんかうまい方法はないもんですかねえ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

eRuby(erb)の HTML エスケープ

何の話? この記事のテーマは eRuby に <%= %> などの手段で文字列を挿入するときの HTML エスケープについて。 「eRuby」はテキスト(要するに文字列)に Ruby のコードを埋め込むことができるテンプレート言語の名前。しかし,この名称よりも「ERB」とか「erb」という呼び方で認識している人のほうが多いかもしれない。 「HTML エスケープ」は < とか & といった文字を &lt; とか &amp; といったものに変換する文字列処理。 eRuby の典型的な応用は HTML の生成なので1,式の値(を文字列化したもの)をそのまま挿入したい場合もあれば,HTML エスケープして挿入したい場合もある。 Ruby on Rails では HTML エスケープについてきちんと意識しなくてもよしなに取り計らってくれたりするが,本記事ではテンプレートエンジンをあらわに扱って処理する場合に知っておきたいことをまとめる。 eRuby のテンプレートエンジンとしては,ERB と Erubi を主に取り上げる。 なお,eRuby という名称や eRuby のテンプレートエンジンについては下記の拙記事も参考にしてほしい。 Erubi とは何か - Qiita ところで,「エスケープ」にもいろいろあるが,本記事では HTML エスケープしか扱わないので,以下では「HTML」を略すことがある。 テンプレートエンジン eRuby のテンプレートエンジンはいくつもあるが,2021 年時点では,標準添付ライブラリーの ERB と,Rails で採用されている Erubi だけ知っておけばいいと思う。 本記事では説明の都合で,Erubi の前身にあたる Erubis にも触れる。 歴史的には ERB → Erubis → Erubi の順に現れた。 以下,本記事では「ERB」という表記は標準添付ライブラリーで定義された ERB クラスのみを指すこととする。テンプレート言語の名前は「eRuby」とのみ表記する。 例題 この記事では,単純に "&" という文字列を,HTML エスケープ無しと有りの二とおりに挿入したテキストを生成してみる。 以下,ERB と,Erubis,Erubi で処理するコードを見ていくが,Tilt というライブラリーを援用すると記述が楽で説明もしやすいので,そうする。 ERB の場合 ERB ではテキスト中に式の値(を文字列化したもの)を挿入する手段は <%= %> しかない。 また,HTML エスケープは自動的にはされない。 レンダリングの仕方 では処理コードを見てみよう。 あらかじめ gem install tilt で Tilt をインストールしておき, require "tilt" erb_text = "<%= '&' %>" p Tilt::ERBTemplate.new{erb_text}.render とすれば "&" と表示される。確かにエスケープはされていない。 (require "erb" はあらわに書かなくても require してくれるようだ) コードの意味を少し説明する。 Tilt::ERBTemplate というのは,Tilt で定義された ERB ベースのテンプレート処理クラス2。 eRuby スクリプトを引数ではなくブロックで与えることに注意されたい。 一方,eRuby スクリプトそのものではなく,eRuby スクリプトのファイルパスを与える場合はブロックではなく引数として与える。 出来たオブジェクトの render メソッドを呼べばレンダリングした結果が返る。 エスケープさせたいときは エスケープさせたいときは,エスケープ用のメソッドを使う。 たとえば標準添付ライブラリーの cgi/escape には escapeHTML というメソッドが定義されている。 こんなふうに使える: require "cgi/escape" puts CGI.escapeHTML("&") # => "&amp;" しかし,ERB クラスには ERB::Util という小さなモジュールが定義されていて,そこに html_escape というメソッドと,そのエイリアスである h メソッドが定義されているので,これを使えばよい。 このメソッドは require "erb" p ERB::Util.h("&") # => "&amp;" のように使える。 ERB::Util のメソッドはいわゆるモジュール関数として定義されているので,(ちょうど Math モジュールの関数たちと同じように)モジュールの特異メソッドしてだけでなく, require "erb" include ERB::Util p h("&") # => "&amp;" のような使い方も可能だ。 このモジュールを使えば,"&" をエスケープして挿入する eRuby スクリプトは <%= h("&") %> のように書くことができるはずだ。 あるいはもっとシンプルに <%=h "&" %> と書いてもいい。h の前にスペースを書かなかったのは,まあなんというか,癖というか好みのようなもの。 では eRuby スクリプト中で h メソッドが使えるようにするにはどうすればよいのか? それには,h メソッドを持つオブジェクトを render メソッドに与えればよい。このようなオブジェクトを「スコープ」と呼ぶらしい。 具体的には,以下のようにする。 require "tilt" require "erb" erb = "<%=h '&' %>" scope = Object.new scope.extend ERB::Util p Tilt::ERBTemplate.new{erb}.render(scope) # => "&amp;" オブジェクトを一つ作って,ERB::Util を extend し,それを render に引数として与えればよいのだ。 scope を作るところは一行で scope = Object.new.extend(ERB::Util) と書いてもいい。 余談だが,eRuby スクリプトに埋め込まれた Ruby コード部分では,render メソッドにスコープとして渡されたオブジェクトが self になる。 したがって,もし上記のコードで scope がインスタンス変数 @foo を持っていたとしたら,eRuby スクリプト中でそれを直に @foo として参照することができる。 Erubis と Erubi Erubis と Erubi では,式の値(を文字列化したもの)を挿入する手段として <%= %> のほかに <%== %> がある。 両者の違いはエスケープされるかどうかだけ。 デフォルトでは <%= %> エスケープされない <%== %> エスケープされる なのだが,オプションにより逆にすることができる。 レンダリングの仕方 Erubis と Erubi は同じ使い方なので,Erubi のコードで示す。 require "tilt" erb_text = "<%= '&' %> <%== '&' %>" p Tilt::ErubiTemplate.new{erb_text}.render # => "& &amp;" Erubis の場合は Tilt::ErubiTemplate を Tilt::ErubisTemplate に変えるだけ。 結果を見ると,確かに <%= %> エスケープ無し <%== %> エスケープ有り となっている。 エスケープの有無を逆転させるには おそらく eRuby を書いたことのある人の多くは(デフォルトの逆の) <%= %> エスケープ有り <%== %> エスケープ無し に馴染んでいると思う。 Ruby on Rails がバージョン 3 以降そうなっているからだ。 もっとも,Rails の場合,ActiveSupport::SafeBuffer という String を継承したクラスを導入して,エスケープすべきかどうかを自動判定してよきに計らってくれるようになっているので,<%== %> はあまり出番が無いかもしれない。 Rails については本記事のテーマを外れるので,これ以上触れない。 エスケープの有無を上記のように逆転させるには,escape というオプションをキーワード引数として与え, require "tilt" erb_text = "<%= '&' %> <%== '&' %>" p Tilt::ErubisTemplate.new(escape: true){erb_text}.render # => "& &amp;" とすればよい。 結果を見れば,確かにデフォルトとはエスケープの有無が逆になっている。 オプションで逆ってややこしい? オプション如何で <%= %> と <%== %> の意味が全く逆になり,しかも世間ではデフォルトと逆の設定が普通である,という状況はややこしくないだろうか? eRuby スクリプトだけを見たのでは <%= %> の意味がどちらであるか分からないのだ。 ここからは推測だが,こうなっているのは歴史的な事情ではないかと思う。 既に見たように ERB ではエスケープするために式の中でエスケープ用メソッドを使う必要があった。 Erubis は <%== %> という形式を新たに付け加えることで,自動エスケープ機能を実現した。 ここでこういう考え方が起こる(完全に憶測というか妄想)。HTML 生成において,エスケープはセキュリティーに関わる重大事である。「うっかり h を書き忘れた」は許されない3。自動エスケープこそが基本であるべきではないか。 なので,最もシンプルな <%= %> をエスケープ有りとし,複雑な <%== %> をエスケープ無しとする設定を用意したところ,多くのユーザーに支持された。そういうことではないのか。 こういう話は,Erubis のドキュメントか,Rails 3 のドキュメントに書いてあるかもしれないが,もう(私には)見つけられない。 私もこちら(<%= %> がエスケープ)を断然支持する4。経験上,うっかり <%= %> とすることはあっても,うっかり <%== %> とすることはまず無いからだ。それにイコールを二つ重ねたほうがいかにも「そ・の・ま・ん・ま」感があるし。 最初からそうなってればよかったのに,と思わなくもないが,ERB との互換性を考慮してこういう仕様になっているのかもしれない。 余談だが,eRuby とは全く違うテンプレートシステム Slim でも,= で「エスケープ有りの挿入」,== で「エスケープ無しの挿入」となっている。 eRuby は汎用のテンプレート言語であり,生成するテキストは HTML に限らない。 ↩ 「テンプレート処理クラス」という表現は苦し紛れに考えたもので,どう呼ぶのが妥当なのか知らない。しかし「テンプレートエンジン」と呼ぶのは問題があると思う。 ↩ しかし,実際しばしば書き忘れるのである。 ↩ もっとも,私は HTML をほぼ Slim で書くので,HTML 生成に eRuby を使う機会はほとんどないのだが。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む