20211016のRailsに関する記事は7件です。

テストコードについて!

①.結論! テストコードとは、アプリケーション内に記述する、そのアプリケーションの挙動を確認するためのコードのことです! Ruby on Rails内にも、アプリケーションのテストコードを記述する機能を設けることが出来ます! その機能は「RSpec」というGemを使うことで便利に実装できます! ②.なぜテストコードを書くのか? テストコードを書く意義は大きく分けて2つあります! 1・クオリティの担保ができる! ブラウザデアピリケーションの挙動を確認するのは、デメリットの方が多いです! 主な理由は3つです! ・人為的なミスが生じるかもしれない! ・仕様が変更した際に、もう1度全部やらないといけない! ・どのように確認したか、記録が残らない! このようなことがあります! 2・仕様を見極めることが出来る! テストコード書くことが出来れば、アプリケーションの仕様を理解していることになる! 主な理由は2つです! ・テストすべき項目を洗い出すときに使用を見極めることが出来る! ・テストコードを書ける人は、仕様を理解している人! 以上が、テストコードを書くための理由になります! ③.テストコードのパターン(正常系と異常系) アプリケーションの挙動を確認するときは、「うまくいくとき」「うまくいかないとき」をそれぞれ確認する必要があります! 例えば、「うまくいくとき」は、「画像URLとテキストの両方を入力して送信すると、テーブルに保存できる」というケースです! 一方で、「うまくいかないとき」は、「画像URLもテキストも入力せずに送信ボタンを押すと、テーブルに保存されない」というケースです! テストコード書く際は、前者を正常系、後者を異常系と呼びます! ・正常系 「ユーザーが開発者の意図する操作を行った時の挙動」を確認するテストコードが、正常系に分類されます! ・異常系 「ユーザーが開発者の意図しない操作を行った時の挙動」を確認するテストコードが、異常系に分類されます! 例えば、必須項目を入力せずに送信した際は、「必須項目を入力してください」とアラート画面などがでることがあります! この挙動を確認することは異常系に分類されます! ④.テストコードの種類(単体と結合) テストコードの種類は、大きく2つあります! 1つ目が、実装した機能を部分的に意図通りに動作するか確認する単体テストです! 2つ目が、ユーザーがその機能を使う際、一連の動作が問題なく行われるかを確認する結合テストです! ・単体テストコード モデルやコントローラーなどの機能ごとに問題がないか確かめます! 例えば、モデルのテストコードでは「画像URLとテキストがない投稿は、テーブルに保存させない」というバリデーションの挙動を確認します! ・結合テストコード ユーザーがブラウザで操作する一連の流れを再現して、問題がないか確かめます! 例えば、投稿のテストコードでは「画像URLとテキストを投稿して送信ボタンを押すと、投稿完了ページに移動し、TOPページに戻ると、投稿した内容が表示されている」という流れを一気に確かめます! 簡単に言うと、単体は各機能ごとに行い、結合はユーザーの操作を再現して一連の流れを行うと言う事です! .⑤まとめ Ruby on Railsでテストコードを書く際は、RSpecを使用することが多いみたいですね! このテストコードがきちんと書けるようになれば、仕様を理解している事になるので、きちんと覚えて行こうと思います! 簡単にまとめて言うとこんな感じです! アプリケーションの挙動はテストコードを実行することで確認できる! テストコードを書くことで、アプリケーションの品質が担保されるだけではなく、設計を読み解くこともできる! テストコードは正常系と異常系に大きく分類される! テストコードは、単体テストコードと、結合テストコードの2種類がある! しっかり覚えて行こうと思います! 何か説明で間違っていたらご指導お願い致します(_ _)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]パーシャル内パーシャルのrender繰り返しを防ぐには

ハマった点 投稿一覧ページに「いいねボタン」を設置する際、各投稿のパーシャルをrenderする際の繰り返しは、collectionオプションにて解決できた。 しかし、各投稿のパーシャルの中でrenderしているパーシャルにおいては、投稿の分だけrenderの繰り返しが発生してしまう。  ↓実際のログ このrenderのせいで、たった25件の投稿表示に1800ms以上の時間がかかってしまう。しかも、Ajaxによる非同期処理でいいねボタンの切り替えを実装しているため(DRYの観点でも)、いいねボタンをパーシャル化しなければならない。(他に方法があれば知りたいです!) 同じ状況の方も多いのでは? 解決策 renderのlayoutオプションとyieldメソッドを使うことで解決した。 ER図 [NGパターン] renderの繰り返しが発生するrenderの使い方 コントローラー posts_controller.rb def index @posts = Post.All # 今回はN+1問題などは考慮しません end View views/posts/index.html %div = render partial: 'posts/shared/post', collection: @posts, as: :post views/posts/shared/_post.html %div = post.id = post.content .post-likes{ id: "post-#{post.id}-likes" } = render 'likes/like', post: post views/likes/_like.html - if post.already_liked?(current_user) # 「いいね」済みならtrueを返すメ = link_to post_like_path(post, post.likes), mehod: :delete, remote: true do %font .fas.fa-heart.likes-heart-already - else = link_to post_likes_path(post), method: :post, remote: true do %font .far.fa-heart %span{ id: "post-#{post.id}-likes-count" } = post.likes.count ログ terminal web_1 | ↳ app/controllers/application_controller.rb:36 web_1 | Rendering posts/index.html.haml within layouts/application web_1 | Rendered likes/_like.html.haml (7.7ms) web_1 | Rendered likes/_like.html.haml (0.6ms) web_1 | Rendered likes/_like.html.haml (0.6ms) web_1 | Rendered likes/_like.html.haml (0.5ms)                                                  〜省略〜 web_1 | Rendered likes/_like.html.haml (0.6ms) web_1 | Rendered likes/_like.html.haml (0.4ms) web_1 | Rendered likes/_like.html.haml (0.4ms) web_1 | Rendered collection of posts/shared/_post.html.haml [25 times] (663.9ms) web_1 | Rendered posts/index.html.haml within layouts/application (690.5ms) web_1 | Completed 200 OK in 1847ms (Views: 1791.0ms | ActiveRecord: 3.4ms) [OKパターン] renderの繰り返しが発生しないrenderの使い方 コントローラー posts_controller.rb # コントローラは改善前と同じです。 def index @posts = Post.All # 今回はN+1問題などは考慮しません end View ↓ renderメソッドのlayoutオプションを使い、パーシャルに_like.htmlを指定。さらに、collectionにはpostsを指定する。 views/posts/index.html .posts-wrap %div{ id: 'post-items' } = render partial: 'likes/like', layout: 'posts/post_layout', collection: @posts, as: :post / _post_layoutパーシャルは新たに作成します。 ↓ yieldメソッドにて_like.htmlパーシャルを表示する。 views/posts/post_layout.html %div{ id: "post-#{post.id}" } %div = post.id = post.content .post-likes{ id: "post-#{post.id}-likes" } = yield / このファイルはは新たに作成しています。 ログ terminal web_1 | ↳ app/controllers/application_controller.rb:36 web_1 | Rendering posts/index.html.haml within layouts/application web_1 | Rendered collection of likes/_like.html.haml [25 times] (33.6ms) web_1 | Rendered posts/index.html.haml within layouts/application (61.2ms) web_1 | Completed 200 OK in 343ms (Views: 295.7ms | ActiveRecord: 2.9ms) 1847msも要していたアクセス時間を343msまで短縮することができました!(正確には短縮ではないですが) おわり なんとなく理解した気でいたrenderメソッドとyieldメソッドについて理解を深めることができました。 解決までに時間がかかってしまったので、解決できた時は本当に感動しました。 初めての投稿で、わかりづらい点があるかもしれません。 意見、アドバイス等よろしくお願いします! 今後も学びのアウトプットをしていきたいと思います。 参考にした記事 忘れがちなrenderメソッドの使い方まとめ [Rails] Railsのpartialでcollectionを渡すときにはindexの変数が自動的に作られる Railsドキュメント - render
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Prefix_pathに引数を入れる理由

こんにちは!テックアカデミーのWebアプリコースを受講している駆け出し高校生エンジニアの安田駿介です。 今回は、「Ruby <%= %>内でstyle要素を書く方法」というテーマで解説していきます。 Prefix_pathに引数を入れる理由 結論を言うと、Prefix_pathで呼び出すURLに、引数の内容を補足するためです。 例えば、 というコードがあったとします。 このコードの意味は、「作成したレコード一覧のページを表示する」です。 これに(current_user)という引数を指定すると、 「ログインしているユーザの作成したレコード一覧」という意味になります。 開発環境 ・Cloud9 ・Ruby 3.0.0 ・Rails 6.1.3.1
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】Qiita デイリー LGTM 数ランキング【自動更新】

他のタグ AWS Android Docker Git Go iOS Java JavaScript Linux Node.js PHP Python Rails React Ruby Swift TypeScript Vim Vue.js 初心者 集計について 期間: 2021-10-16 ~ 2021-10-17 GitHub スターをもらえるととっても励みになります LGTM 数ランキング 1 位: [Rails] 「ゲームセンターを救いたい!」という想いでポートフォリオ作りました。 Rails 初心者 ポートフォリオ 5 LGTM 1 ストック @aaaasahi_17 さん ( 2021-10-16 16:01 に投稿 )
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] 「ゲームセンターを救いたい!」という想いでポートフォリオ作りました。

アケイベ アプリ概要 コロナ渦で消えゆくゲームセンターを救いたい! という気持ちで作成したゲームセンター開催限定のイベント投稿型サービスです。 作成した背景 ゲームセンター を救いたいという想い 私は元々ゲームセンターで働き、休日でも都内各地のゲームセンターに通うくらいゲームセンター独特の雰囲気、コミュニティが大好きでした。 そんな大好きなゲームセンターがコロナ渦で続々と閉店していくのを見て今の自分に何ができるのかを考え作成しました。 イベント投稿型にした理由は、 イベントを開催することでコミュニティが広がるだけじゃなく集客にも繋がりやすい。 ゲームセンター側での告知(Twitter、HP)だけでは限界があることを知っている。 イベント主催者をお客さん側に任せることでゲームセンター側の人件費が減らせる。 という点からです。 開発で工夫したこと N+1問題を解消し処理時間を短縮させた 投稿が増えるにつれて読み込み時間が長くなるのはユーザーが利用する上で不便になると感じました。 原因を調べるためにターミナルでログを確認したところ、N+1問題が発生していることが分かったのでN+1問題を検知するbulletというgemがあることを知り、こちらを導入して問題箇所を特定。 主に画像投稿機能として使用したactive storageによるものだと分かったのでActive Storage上で用意されたwith_attached_attachment_nameというスコープを使用することで読み込み時間を短縮することができました。 運用を考えたオリジナルの管理者機能 運用する上でサービスのアクティブ状況が分かるアナリティクス機能を入れたかったのでオリジナルの管理者機能を作成しました。 主な機能としては、 ユーザー登録状況、イベント投稿状況をChartで表示 全てのユーザー、イベント情報と前日のユーザー、イベント情報を表で表示しPDF出力可能に バッジ処理とAction Mailerを使用しAdmin Userに現在のユーザー、イベント数と前日のユーザー登録数、イベント投稿数を毎朝6時にメール配信 今後迷惑な投稿やユーザーを削除できる機能を追加予定です。 実際の使用イメージ 特に見て欲しい点 小さく作りgithubのリポジトリとして残すまたQiitaにも投稿 各機能を実装する際、ただ実装して終わりではなく、機能ごとにGitHubにリポジトリを作りドキュメント化することで記憶ではなく記録に残るようにしました。 GitHubにリポジトリとして残すことで次回同じ機能を実装する際その機能を前回より早く実装することができます。 GitHubリポジトリ一覧、 - タグ機能 - Google Map APIを使用したMAP表示 - DM機能 Qiitaに投稿することは実装内容を自分の言葉で整理し誰が読んでもわかるように書かなくてはなりません。その結果内容を深く理解することができました。 Qiita記事一覧、 言語切り替え ゲームセンターで働いていた際、お客様として日本だけでなく海外の方もよく来店されることがあったので海外の方でもこのサービスを使ってもらえるようページ下の言語ボタンを押すことでほぼ全てのページで言語切り替えに対応しています。 現在対応しているのは英語だけですが今後使用人口の多い中国語やスペイン語など様々な言語に対応していきたいです。 開発で苦労したこと イベント自動閉鎖機能 イベント開催日が過ぎたイベントを自動で閉鎖する機能。ネット上に参考文献がなく、自力で実装していく必要がありました。 機能要件を作成し実装の手順を具体的にしてから実装しました。 具体的な方法は、下記になります。 イベントの期日が過ぎたイベントを論理削除する イベントカラムにbooleanを持たせる 開催日が過ぎたイベントのbooleanの状態でViewの表示を変更する 論理削除はイベント期日が過ぎたら自動で実行 イベント開催日が過ぎたらbooleanを変更するメソッドを定義 そのメソッドをrakeタスクに登録 rakeタスクを定期実行する この経験から、未知の機能に対して自ら要件を定義し分解して解決するための試行錯誤とやり遂げる経験を得ました。 この時の様子をQiitaにもまとめました。 Action Textの内容で検索できない問題 イベント投稿のエディターとしてaction text、検索機能としてgem ransackを使用していたのですがAction Textとransackの相性が悪くAction Textで投稿した内容で検索ができないという不具合が発生しました。 なぜ動かないのかという現状を把握した上でSQLの内部結合を用いてAction Textの内容でも検索できるように検索機能を自作しました。 この経験から不具合に対しては現状を把握すること、gemではなく自作で作る対応力と実装力を得ました。 この時の様子をQiitaにもまとめました。 その他工夫したこと 20以上の機能数 大手イベントサービスを参考に直感でわかるUI Rubocopを導入してコードの品質を担保 RSpecを使用して、約100件のテストコード 実際のWebサービスを想定し本番環境にAWSを採用 現役エンジニアにコードレビューを受け改善 機能一覧 ユーザー機能一覧 新規登録、ログイン機能(devise) ゲストログイン機能 管理者機能一覧 ユーザー、イベント状況Chart表示(chartkick) ユーザー、イベント情報PDF出力(wicked_pdf) イベント、ユーザー情報管理者にMail定期配信(whenever) イベント機能一覧 イベント投稿機能 画像投稿機能 画像プレビュー機能 カテゴリ投稿機能(active hash) 住所投稿によるMAP表示機能(Google API) タグ投稿機能 イベント詳細機能 コメント機能 参加機能(Ajax) クリップ機能(Ajax) イベント編集、削除機能 カレンダー機能(SimpleCalendar) パンクズ機能(gretel) 検索機能一覧 キーワード検索(ransack) カテゴリ検索 タグ検索 ソート機能 ページネーション機能(kaminari) マイページ機能一覧 投稿、参加、クリップしたイベントの一覧表示機能 DM機能 プロフィール編集機能 Email Password変更機能 退会機能 その他 通知機能 イベントClose機能(whenever) 言語切り替え機能 テスト機能(rspec) 使用技術 言語:Ruby (3.0.0) フレームワーク:Ruby on Rails (6.1.3) フロントエンド:HTML/Scss/JavaScript DB:PostgreSQL インフラ:AWS (VPC | RDS | EC2 | S3 | Route53 | ACM| ALB) ソースコード管理:GitHub ER図 今後追加したい機能 迷惑ユーザー、投稿に対して管理者が削除する機能 言語切り替え 日本語と英語以外の言語の追加 通知機能の範囲拡大 画像複数投稿機能 感想と反省点 課題解決のための設計を1から作り開発する過程や、エラー解決、オリジナルの機能を作るために試行錯誤したことはとても楽しく夢中になりました。 反省点としては、 自分の作りたいものにこだわりすぎて開発期間が長くなってしまったこと、 PFを作り始めるまでの勉強期間を長く取りすぎたことです。 個人開発は勉強している時には気付けなかった予想外のことが沢山起こるため個人開発をしながらその場その場で足りない知識を補っていくというのが一番効率のいい勉強法だと気付けました。 これからも個人開発を続けスキルアップすると共に、困っている人の課題を解決できるようなサービスを作っていきたいです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【図解】Hotwire : Turbo 7つのアクション

はじめに チュートリアルでHotwireの基本を学んだ後に、Railsアプリでサンプルページを作りながら、Turboで用意されてる7つのアクションについて動作確認した結果を図解しました。 Turboで用意されてる7つのアクション Append / Prepend Replace Update Remove Before / After ざっくり見たい方向け 公式ドキュメント Turbo Reference アクション append appendは指定したTurboFrameの中の最後に要素を追加します。 図解 サンプルコード(Rails:抜粋) ユーザ一覧の最後にユーザを追加。 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'append' do %> <%= link_to 'append', append_path %> <% end %> users_controller.rb def index @users = User.first(3) end def append @users = User.last(3) render layout: false, content_type: 'text/vnd.turbo-stream.html' end append.html.erb <%= turbo_stream.append "users" do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> prepend appendは指定したTurboFrameの中の先頭に要素を追加します。 図解 サンプルコード(Rails:抜粋) ユーザ一覧の先頭にユーザを追加。 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'prepend' do %> <%= link_to 'prepend', prepend_path %> <% end %> users_controller.rb def index @users = User.first(3) end def prepend @users = User.last(3) render layout: false, content_type: 'text/vnd.turbo-stream.html' end prepend.html.erb <%= turbo_stream.prepend "users" do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> replace replaceは指定したTurboFrameを上書きします。 図解 サンプルコード(Rails:抜粋) ユーザ一覧をアイテム一覧に置き換える。 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'replace' do %> <%= link_to 'replace', replace_path %> <% end %> users_controller.rb def index @users = User.first(3) end def replace @items = Item.first(3) render layout: false, content_type: 'text/vnd.turbo-stream.html' end replace.html.erb <%= turbo_stream.replace "users" do %> <%= turbo_frame_tag 'items' do %> <% @items.each do |item| %> <div id="<%= dom_id item %>"><%= item.name %></div> <% end %> <% end %> <% end %> update updateは指定したTurboFrameの内容を更新します。 図解 サンプルコード(Rails:抜粋) ユーザ一覧を更新。 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'update' do %> <%= link_to 'update', update_path %> <% end %> users_controller.rb def index @users = User.first(3) end def update @users = User.last(3) render layout: false, content_type: 'text/vnd.turbo-stream.html' end prepend.html.erb <%= turbo_stream.update "users" do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> remove removeは指定したTurboFrameを取り除きます。 図解 サンプルコード(Rails:抜粋) ユーザ一覧を削除 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'remove' do %> <%= link_to 'remove', remove_path %> <% end %> users_controller.rb def index @users = User.first(3) end def remove render layout: false, content_type: 'text/vnd.turbo-stream.html' end remove.html.erb <%= turbo_stream.remove "users" %> before beforeは指定したTurboFrameの前に要素を追加します。 図解 サンプルコード(Rails:抜粋) ユーザ一覧の前にアイテム一覧を追加。 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'before' do %> <%= link_to 'before', before_path %> <% end %> users_controller.rb def index @users = User.first(3) end def before @items = Item.first(3) render layout: false, content_type: 'text/vnd.turbo-stream.html' end before.html.erb <%= turbo_stream.before "users" do %> <%= turbo_frame_tag 'items' do %> <% @items.each do |item| %> <div id="<%= dom_id item %>"><%= item.name %></div> <% end %> <% end %> <% end %> after afterは指定したTurboFrameの後に要素を追加します。 図解 サンプルコード(Rails:抜粋) ユーザ一覧の後ろにアイテム一覧を追加。 index.html.erb <%= turbo_frame_tag 'users' do %> <% @users.each do |user| %> <div id="<%= dom_id user %>"><%= user.name %></div> <% end %> <% end %> <%= turbo_frame_tag 'after' do %> <%= link_to 'after', after_path %> <% end %> users_controller.rb def index @users = User.first(3) end def after @items = Item.first(3) render layout: false, content_type: 'text/vnd.turbo-stream.html' end after.html.erb <%= turbo_stream.after "users" do %> <%= turbo_frame_tag 'items' do %> <% @items.each do |item| %> <div id="<%= dom_id item %>"><%= item.name %></div> <% end %> <% end %> <% end %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【個人用】rails tutorial -2

本章の学習内容 大量の機能を自動生成するscaffoldジェネレータというスクリプトを使ってアプリケーションを生成し、高度なRailsプログラミングとWebプログラミングの概要を学ぶこと ユーザーモデルの設計 各ユーザーには、重複のない一意のキーとなるinteger型のID番号(idと呼びます)を割り当て、このIDに加えて一般公開されるstring型の名前(name)、そして同じくstring型のメールアドレス(email)を持たせます。emailはユーザー名としても使われる マイクロポストのモデル設計 テキスト内容を格納するtext型のcontentだけで構成されています 。しかし実際には、マイクロポストをユーザーと関連付ける必要があります。そのため、マイクロポストの投稿者を記録するためのuser_idも追加します。 Usersリソース ユーザー用のデータモデルを、そのモデルを表示するためのWebインターフェイスに従って実装。このデータモデルとWebインターフェイスは、組み合わさることで Usersリソースとなり、ユーザーというものを、HTTPプロトコル経由で自由に作成/取得/更新/削除できるオブジェクトとみなすことができるようになる。今回はUsersリソースはすべてのRailsプロジェクトに標準装備されているscaffoldジェネレータで生成する scaffoldについて rails generateスクリプトにscaffoldコマンドを渡すことで生成されるものでscaffoldコマンドの引数には、リソース名を単数形にしたもの(この場合はUser)を使い、必要に応じてデータモデルの属性をオプションとしてパラメータに追加 $ rails generate scaffold User name:string email:string name:stringとemail:stringオプションを追加することで、Userモデルの内容が`次のようになる なお、idパラメータはRailsによって自動的に主キーとしてデータベースに追加されるため、追加不要 続いてToyアプリケーションの開発を進めるには、次のようにrails db:migrateを実行してデータベースをマイグレート(migrate)する必要がある $ rails db:migrate マイグレーションを実行したことで、ローカルWebサーバーを別タブで実行できるようになる scaffoldでusersリソースを生成したことでユーザー管理用ページに次の幾つかのページが追加される URL アクション 用途 /users index 全ユーザーを一覧するページ /users/1 show id=1のユーザーを表示するページ /users/new new 新規ユーザーを作成するページ /users/1/edit edit id=1のユーザーを編集するページ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む