20210912のRailsに関する記事は20件です。

[rails] nginx + unicorn + mysql (aws EC2 RDS) production環境立ち上げ時のメモ

はじめに 初心者がRailsチュートリアルのやり方を無視アレンジして無謀にもAWSでデプロイしたためにエラー地獄にハマった軌跡をメモとして残しました。 (ミドルウェアもチュートリアルと変えてます。WEBサーバー:nginx + unicorn、DB:mysql(RDS)) 参考記事 「rails aws」で検索して上位に出てきた こちらの記事を参考(めちゃくちゃ助かりました。) 環境 Rails 6.0.3 ruby 3.0.2 unicorn v6.0.0 nginx/1.20.1 mysql 8.0.2 unicorn.rb listenのパスを{app_name}/tmp/unicorn.sock に変更する(pidも同様)。こちらにある通り、参考記事は古い記述になってるので上記の通り変更することでNginxとの接続が可能になるらしい。 credentials.yml.enc さらにRails5.2以降はsecret.ymlがcredentials.yml.encになったらしい。{app_name}/で以下を実行で編集&master.key作成 (master.keyは.gitignoreに入るのでproduction環境は手動で作成する必要があるらしい。unicorn起動時に意味のわからないエラーの原因の1つはこれでした。このあたりで結構ハマった...) $ EDITOR="vi" bin/rails credentials:edit ちなみにcredentials.yml.encは普通にvimで直接編集できないのでこの方法でやる必要があるらしいです。 nginxの設定ファイル デフォルトは/etc/nginx/conf.d/default.confに作られるので{app_name}.confに変更した後に以下の部分を変更。 /etc/nginx/conf.d/rails.conf upstream unicorn { server unix:{app_name}/tmp/unicorn.sock; } おわりに これらの設定を見直した状態でunicorn、nginxなど再起動で無事サーバーが正常起動しました。終わってみれば、参考記事と現行バージョンの差異による設定ファイルの場所や書き方などの変更作業がエラー対処の大半の時間を費やしていた気がします。 aws要素は? aws特に関係ない話になってしまいましたが、DBをチュートリアルのpostgresからmysql(RDS)に変えた部分は大して影響ありませんでした(今のところ)。DB接続周りはdatabase.ymlでhostをRDSのエンドポイントにして、usernameとpassword変えたくらいで問題なかったはずです。VPCのセキュリティグループでRDSとEC2間のポートなどが適切に設定してあればこれくらいの変更でいけると思います。 約15時間にわたる死闘の末 唐突に画面に映ったhello, world!の文字列。ああ、そういえばRailsチュートリアル進めてたんだった…ここまで感動したhello, world!は初めてだよ。もう、ゴールしていいよね…? 参考記事 【Ruby on Rails】unicornをNginx環境下で動かす時の設定方法 【CentOS 7】Nginx + Unicorn で Rails アプリケーションを本番環境で立ち上げる方法 ActiveRecord::NoDatabaseErrorが出た時の対処法 | Rails Ambassador ~Railsの伝道師~ Nginxで「could not build server_names_hash...」エラーが出た時の対処方法 - Qiita "The name org.freedesktop.PolicyKit1 was not provided by any .service files"が表示されたら... - Qiita Rails5.2から追加された credentials.yml.enc のキホン - Qiita MySQLのバージョンを5.1から5.7にしてRubyからMySQLに接続する際にlibmysqlclient_ | tackeyy.com 【Rails】Webサーバー「Unicorn」の基本情報と実装方法 - AUTOVICE 【YAML】Railsのdatabase.ymlについてなんとなく分かった気になっていた記法・意味まとめ - Qiita
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails mapメソッドでchartkickでグラフを量産する

はじめに こんにちは。 Rails6アプリケーションでgem"chartkick"とmapメソッドを使って、対応するデータのグラフを自動的に量産する方法について解説します。 Rails5をお使いの方はchartkick導入時のコマンドが変わるらしいので公式サイトを参考にしてください。 chartkickの導入 まず以下のようにgemfileにchartkickを追記します。 gemfile.rb gem "chartkick" その後いつも通りbundle installします。 yarn addコマンドでWebpackerを走らせて依存オブジェクト(cahrtkick)の追加とインストールを行います。( yarn add の解説 ) terminal bundle install yarn add chartkick chart.js 最後に、javascript:app/javascript/packs/application.jsに以下を追記します。 app/javascript/packs/application.js import "chartkick/chart.js" これでchartkickの導入は完了です。 この後mapメソッドで対応するデータのグラフを自動的に量産する方法を解説するので、「表示したいグラフは1つだけだよ!」という方はchartkick公式サイトを参考にした方が早いかもしれません。 前述 〜データの解説〜 本題に入る前に、グラフ挿入時のコードに出てくるモデルとそのカラム名について紹介します。 データモデルは以下の表の通り。 ExerciseモデルとRecordモデルは1対多のアソシエーションです。 グラフはRecordモデルのweightカラムとreps_countカラムの値をもとに算出されたRMカラムの値とdateカラムの日付で、紐づいたExerciseカラムの数だけ描画します。   Exercise        Record     id    id name exercise_id weight reps_count RM date グラフの挿入 というわけで本題です。 mapメソッドを使って、対応するデータのグラフを自動的に量産する方法を解説します。 exerciseコントローラのindexアクション内でインスタンス変数にExerciseモデルの全てのデータを取得します。 exercises_controller.rb class ExercisesController < ApplicationController def index @exercises = Exercise.all end end 取得したインスタンス変数のレコードの数だけmapメソッドで繰り返します。 mapメソッド内では名前とグラフを出力します。 exercises/index.html.erb <h2>グラフページ</h2> <% @exercises.map do |exercise| %> <br> <%= link_to exercise.name %> <% graph = Record.where(name_id: exercise.id).pluck(:date, :RM) %> <%= line_chart graph, min: 30, max: 45 %> <% end %> 4行目で、名前(mapメソッドで繰り返されているexerciseのnameカラムの値)を出力。 5行目で、Recordモデルのname_idカラムの値とmapで繰り返されているexerciseのidの値が一致するレコードをwhereメソッドで取り出し、そのレコードのdateカラムとRMカラムの値をgraphという変数に配列形式で代入する。 graph = [:date, :RM] 6行目で、5行目で定義したgraph変数の値を使ってグラフを描画。 line_chartはchartkickのコマンドで折れ線グラフの描画を意味します。 オプション引数でグラフの縦軸(RM)の表示範囲を30〜45に定義。 ※ インスタンス変数@exercisesとmap内で繰り返されるexerciseのスペルミスにご注意ください。 これで http://localhost:3000/exercises/index にアクセスするとグラフが表示されます。 参考 今回は折れ線グラフを挿入しましたが、他の種類のグラフを挿入する場合 chartkick公式サイトを参考にしてください。 Twitterで日々の学習をアウトプットしています。 未熟者ですが、ご興味あれば覗いてやってください。→Twitter
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails mapメソッドとchartkickでグラフを量産する

はじめに こんにちは。 Rails6アプリケーションでgem"chartkick"とmapメソッドを使って、対応するデータのグラフを自動的に量産する方法について解説します。 Rails5をお使いの方はchartkick導入時のコマンドが変わるらしいので公式サイトを参考にしてください。 chartkickの導入 まず以下のようにgemfileにchartkickを追記します。 gemfile.rb gem "chartkick" その後いつも通りbundle installします。 yarn addコマンドでWebpackerを走らせて依存オブジェクト(cahrtkick)の追加とインストールを行います。( yarn add の解説 ) terminal bundle install yarn add chartkick chart.js 最後に、javascript:app/javascript/packs/application.jsに以下を追記します。 app/javascript/packs/application.js import "chartkick/chart.js" これでchartkickの導入は完了です。 この後mapメソッドで対応するデータのグラフを自動的に量産する方法を解説するので、「表示したいグラフは1つだけだよ!」という方はchartkick公式サイトを参考にした方が早いかもしれません。 前述 〜データの解説〜 本題に入る前に、グラフ挿入時のコードに出てくるモデルとそのカラム名について紹介します。 データモデルは以下の表の通り。 ExerciseモデルとRecordモデルは1対多のアソシエーションです。 グラフはRecordモデルのweightカラムとreps_countカラムの値をもとに算出されたRMカラムの値とdateカラムの日付で、紐づいたExerciseカラムの数だけ描画します。   Exercise        Record     id    id name exercise_id weight reps_count RM date グラフの挿入 というわけで本題です。 mapメソッドを使って、対応するデータのグラフを自動的に量産する方法を解説します。 exerciseコントローラのindexアクション内でインスタンス変数にExerciseモデルの全てのデータを取得します。 exercises_controller.rb class ExercisesController < ApplicationController def index @exercises = Exercise.all end end 取得したインスタンス変数のレコードの数だけmapメソッドで繰り返します。 mapメソッド内では名前とグラフを出力します。 exercises/index.html.erb <h2>グラフページ</h2> <% @exercises.map do |exercise| %> <br> <%= link_to exercise.name %> <% graph = Record.where(name_id: exercise.id).pluck(:date, :RM) %> <%= line_chart graph, min: 30, max: 45 %> <% end %> 4行目で、名前(mapメソッドで繰り返されているexerciseのnameカラムの値)を出力。 5行目で、Recordモデルのname_idカラムの値とmapで繰り返されているexerciseのidの値が一致するレコードをwhereメソッドで取り出し、そのレコードのdateカラムとRMカラムの値をgraphという変数に配列形式で代入する。 graph = [:date, :RM] 6行目で、5行目で定義したgraph変数の値を使ってグラフを描画。 line_chartはchartkickのコマンドで折れ線グラフの描画を意味します。 オプション引数でグラフの縦軸(RM)の表示範囲を30〜45に定義。 ※ インスタンス変数@exercisesとmap内で繰り返されるexerciseのスペルミスにご注意ください。 これで http://localhost:3000/exercises/index にアクセスするとグラフが表示されます。 参考 今回は折れ線グラフを挿入しましたが、他の種類のグラフを挿入する場合 chartkick公式サイトを参考にしてください。 Twitterで日々の学習をアウトプットしています。 未熟者ですが、ご興味あれば覗いてやってください。→Twitter
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pathの引数について

Rspecでテストを書いているとき、下記の実装に関してpathの引数にtask.projectが使われていることに疑問を感じておりました。 describe 'Task詳細' do context '正常系' do it 'Taskが表示されること' do visit project_task_path(task.project, task) #project_task_path(project, task) ではだめなの? expect(page).to have_content(task.title) expect(page).to have_content(task.status) expect(page).to have_content(task.deadline.strftime('%Y-%m-%d %H:%M')) expect(current_path).to eq project_task_path(task.project, task) end end end 前提条件 taskとprojectがassociationの関係を持つ。 class project < ApplicationRecord has_many tasks end class Task < ApplicationRecord belongs_to :project end 考え方 まず考えるべきなのが、どのようなURLが生成されるべきかということ。 ここではTaskの詳細画面なのでURL/project/id/task/id/show となるべきですね。 次にtaskとprojectがassociationの関係を持つということ。 class project < ApplicationRecord has_many tasks end class Task < ApplicationRecord belongs_to :project end これによりtaskはproject(親)のidを持つことになります。 実際にpathの引数のレコードを調べるとこんな感じ。 (byebug) project #<**Project id: 1**, name: "dolorum", status: "todo", release_date: "2019-05-24", created_at: "2021-06-28 14:23:59", updated_at: "2021-06-28 14:23:59"> (byebug) task #<Task id: 3, title: "Task", status: "done", deadline: "2019-10-17 15:00:00", completion_date: nil, description: nil, **project_id: 2**, created_at: "2021-06-22 10:38:01", updated_at: "2021-06-22 10:38:01"> (byebug) task.project #<**Project id: 2**, name: "repudiandae", status: "todo", release_date: "2019-11-05", created_at: "2021-06-22 10:38:01", updated_at: "2021-06-22 10:38:01"> 注目すべきはproject_id ****の値。 project_id: 1に対しtaskはproject_id: 2を持っていますね。 これはassociationの関係とは言えません。 実際project_task_path(project, task)でもURL自体は生成されますが、これではproject_idが異なるため、生成されるURLのidはassociationの関係ではなくなってしまいます。 project_task_path(project, task) => /project/1/task/3 project_task_path(task.project, task)のようにしてproject(親)のidをtask.projectの返り値から取得することで、生成されるURLはassociationの関係を保つことができます。 project_task_path(task.project, task) => /project/2/task/3 引数の順番を入れ替てみる 以下のような結果から、pathの引数はassociationで定義したことなど関係なく、引数に指定した順番の通りにidを渡すようです。 project_task_path(task.project, task) => /project/2/task/3 # 引数の順番を入れ替えた結果 project_task_path(task, task.project) => /project/3/task/2 なので、引数を指定する際は定義したassociationの関係や、実際のブラウザの挙動を意識して、引数を指定してあげる必要があります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】N+1問題についてのまとめ

N+1問題とは? N+1問題とは、データベースからデータを取り出す際に、大量のSQLが発行されてパフォーマンスが低下してしまう問題のことです。 N+1問題の具体例 railsではallメソッドやfindメソッドを使ってデータベースからデータを取得しています。 ターミナルのログを見ると実際には下のようにその都度SQLが実行されています。 SQL Product Load (2.7ms) SELECT `products`.* FROM `products` usersテーブル id name 1 山田 2 新井 3 田中 4 北川 productsテーブル id product group_id 1 カレー 2 2 魚 1 3 焼肉 3 4 刺身  1 「1人のuserは複数のproductsを持つ関係なので、Userモデルにhas_manyメソッドを定義し、Productモデルにはbelongs_toメソッドを定義します。 UserモデルとProductモデルにアソシエーション定義 UserモデルとProductモデルにアソシエーション定義 # User.rb class User < ActiveRecord::Base has_many :Products end # Product.rb class Product < ActiveRecord::Base belongs_to :User end 全ての所有の商品一覧」をviewで表示したい場合に、controller側で全てのuserをallメソッドで取得し、view側で飼い主の持つproductsをアソシエーションによって下記の様に記述する事が出来ます。 N+1問題が起きてしまうコードを確認 # controller @users = User.all # view @users.each do |user| user.products.each do |product| product.name end end 「User.all」のコードが実行されると、「usersテーブルからusersテーブルの全てのカラム」が取得。 このSQLによって、usersテーブルに1回のアクセス。 次にveiw側。SQLをみると、productsテーブルに対して、4回のアクセスが行われている。 N+1問題が起きてしまうコード @groups.each do |group| group.products.each do |product| cat.name end end # このコードが4回のSQL文を発行 SELECT `products`.* FROM `products` WHERE `products`.`group_id` = 1 SELECT `products`.* FROM `products` WHERE `products`.`group_id` = 2 SELECT `products`.* FROM `products` WHERE `products`.`group_id` = 3 SELECT `products`.* FROM `products` WHERE `products`.`group_id` = 4 eachメソッドで@groupsが持つusersテーブルから全てのレコードを一つずつgroupに入れている。 SQLが「usersテーブルへのアクセスが1回 」に対して「productsテーブルへのアクセスがgroupsテーブルのレコードの数(4回)」発行 このようにアクセス1回に対して、関連するテーブルがN回発行されている1+Nの状況を「N+1問題」と言う。 。 N+1問題の対処法 includesメソッド includesメソッド includesメソッドの使用例 --> @users = User.includes(:user) @users = User.allで取得していた箇所を@users = User.includes(:products)に変更します includesメソッド @users = User.includes(:products) # User.allから変更 # 発行される2つのSQL SELECT `users`.* FROM `users` SELECT `products`.* FROM `products` WHERE `products`.`group_id` IN (1, 2, 3, 4) 2つのSQLが発行されました。1行目は、usersテーブルの全てのレコードを取得するSQL文です。 2行目は、productsテーブルからWHERE句で指定した条件にマッチするレコードを取得しています。 まとめ includesメソッドを使わない場合は、関連するuser_idカラムの値を1つずつ指定して取得していたのでproductsテーブルに4回のアクセスが必要でしたが、IN句でカラムの値をまとめて指定した事によって1回で取得出来るようになりました。includesメソッドを使ってレコードをまとめて取得させる事によって必要以上のSQLを発行する事なく済み,パフォーマンス向上に繋がる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】Sprockets::DoubleLinkErrorを解消する

1.背景 Ruby on Railsを使用して共同開発を行っています。 他の方の実装分を追加後、rails sでサーバーを起動すると表題のエラーが表示されました。 今回はエラー解消の手順と原因を備忘録としてまとめます。 2.環境 mac.os バージョン10.15.6 Ruby 2.7.3 Rails 6.1.3.1 psql (PostgreSQL) 12.6 3.該当のエラーと原因 今回のエラーは下記です。 ActionView::Template::Error (Multiple files with the same output path cannot be linked ("top.css") In "/Users/hogehoge/rails/team_project/app/assets/config/manifest.js" these files were linked: - /Users/hogehoge/rails/team_project/app/assets/stylesheets/top.css - /Users/hogehoge/rails/team_project/app/assets/stylesheets/top.scss ): エラーの原因は cssとscssが干渉している 拡張機能「Live Sass Compiler」が起動していた この2点でした。 scssは別の方が実際に実装されたファイルです。 拡張機能が加わり、自動で「top.css」と「top.css.map」が作成された結果、干渉してエラーが発生していました。 4.解消方法 解消方法としては単純でした。今回の場合だと、 「top.css」と「top.css.map」の2つを削除するとエラーが解消され、サーバーの起動が実行されました。 5.拡張機能「Live Sass Compiler」について Live Sass CompilerはVS Codeの拡張機能の一つで、Sass(Scss)を自動でコンパイルしてCSSに変換します。 拡張機能を使用するには、2つの方法があります。 (1)コマンドで下記を入力する Live Sass: Compile Sass (2)VSCodeのステータスバーにあるWatch Sassをクリックする 今回の場合、Watch Sassをクリックすることで自動でコンパイルされていました。 (気づかないうちにクリックしていたようです...) 6.参考 1.Sprockets::DoubleLinkError を解消した方法 2.VSCodeでSass(Scss)を自動コンパイルする簡単な設定方法 3.Visual Studio Code で Sass をコンパイルする Live Sass Compiler 7.最後に 記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。 読んでいただき、ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【第13章】Railsチュートリアルでheroku pg:reset DATABASEを実行時に警告がでる

Railsチュートリアル第13章(第6版)で、herokuでレコードを削除する際に手間取ったので備忘として記録する。 ①heroku pg:reset DATABASEを実行すると警告がでる チュートリアル終了時にherokuのDBをリセットしようとすると、Warning: Cannot open browserが表示されて実行されない。 ②解決方法 heloku login --interactiveを実行すると、正常にログインできる。 参照:https://qiita.com/yadon/items/db3ec786ec410990cec6 ③再度heroku pg:reset DATABASEを実行 表示されるメッセージ通りに入力すれば、成功する。 参照:https://qiita.com/kakiuchis/items/5597354b1901c1371c9e
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

廃棄PCのantix上にrubyonrails環境構築テスト

rubyonrails-test 家の廃棄予定のノートPC(Pentium)にantixをいれて、rubyonrails+node.js環境構築のテスト rubyは新しいものがいれられなかったため、2.6.3をビルドしている 結論:nodeがうまくいれられずに断念 環境構築 mac VSCode拡張 Ruby HTML Snippets Rubyのインストール # update brew update # rbenv brew install rbenv ruby-build echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bash_profile # readline brew install readline brew link readline --force # ruby RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)" # install ruby rbenv install 2.6.3 # use ruby rbenv global 2.6.3 rbenv rehash # check ruby version ruby -v 環境構築 antiX antiX install 基本デフォルトでインストール CDにやいてCDからブートcli-installer 参考 https://antixlinux.com/forum-archive/install-using-the-cli-installer-t3041.html 時刻設定だけ東京に変更 設定終わってログインしたらsudo apt update && sudo apt upgrade grubの更新がされているので全てのディスクにインストールをする(BIOSありの場合) 必要あればネットワークとかの設定を行うantiX-cli-cc 環境構築 antiX rbenv ruby gem bundler sudo apt update sudo apt install -y gcc make bzip2 git libssl-dev libreadline-dev zlib1g-dev sudo apt update git clone https://github.com/rbenv/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc # reload bash source ~/.bashrc mkdir -p "$(rbenv root)/plugins" # rbenv プラグインをインストール git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)/plugins/ruby-build" # rbenv install 後に ~/.rbenv/default-gems に記載の gem をインストールしてくれる git clone https://github.com/rbenv/rbenv-default-gems.git "$(rbenv root)/plugins/rbenv-default-gems" echo bundler > "$(rbenv root)/default-gems" # $ rbenv update すると、~/.rbenv/plugins 以下を全部 git pull してくれる ruby-build も対象となる git clone https://github.com/rkh/rbenv-update.git "$(rbenv root)/plugins/rbenv-update" sudo apt update rbenv install 2.6.3 rbenv global 2.6.3 rbenv rehash # check version ruby -v gem -v bundler -v node.js npm # get setup.sh # execute setup.sh curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash source ~/.profile curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update && sudo apt-get install yarn
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails + React 画像読み込み方法

手順 画像ファイルを app/assets/images へ配置 config/webpacker.yml に追記 jsx ファイルに Component を作成 1. 画像ファイルを app/assets/images へ配置 適当な画像ファイルをapp/assets/imagesへ配置します。 2. config/webpacker.yml に追記 config/webpacker.yml # Additional paths webpack should lookup modules # ['app/assets', 'engine/foo/app/assets'] # resolved_pathsを下記のように変更 resolved_paths: ["app/assets/images"] 3. jsx ファイルに Component を作成 test.jsx import Image from 'test.png'; export default function TestComponent(props) { // ImageComponent 作成 const ImageComponent = p => <img src={Image} /> return ( // ImageComponent 読み込み <ImageComponent></ImageComponent> ); } 参考 Rails × React で画像を読み込む方法 https://forestbook-freelance.com/2021/04/12/rails-x-react-%E3%81%A7%E7%94%BB%E5%83%8F%E3%82%92%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80%E6%96%B9%E6%B3%95/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラー【Module not found: Error: Can't resolve '@popperjs/core'】が分からんかった

Rails6でwebpackerを起動したときに出たエラー % bin/webpack-dev-server ... ERROR in ./node_modules/bootstrap/dist/js/bootstrap.esm.js Module not found: Error: Can't resolve '@popperjs/core' in '/Users/username/hoge_app/node_modules/bootstrap/dist/js' 入れているBootstrap5とpopperjsを使っている場合、入れ方の問題のよう。 yarnでBootstrapを入れているときは確認しておきたい % yarn add @popperjs/core Bootstrap5でpopperjsを使うときは上のコマンドで入れてからwebpackerを立ち上げたら無事立ち上がった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gemfileで使われる「~>」とは

「~>」とは 今後のバグ修正のみ受け入れたい場合に使用する。 # 6.1.3以上、6.2.0未満 gem 'rails', '~> 6.1.3' # 4.1.0以上、5.0.0未満 gem 'puma', '~> 4.1' 参照
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

masterブランチで作業してしまった時の対処法

<手順> 1, まずは修正内容を確認する。 $ git status #ターミナルに作業した内容、変更した内容が出てくる 2, 修正内容を別の場所に一時保管する。 $ git stash その後もう一度git statusをすると先ほどの修正内容はなくなり、ターミナルに下記のような文章が出るはず。 On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean 3, 本来作業をしたかったブランチに切り替えorブランチ作り切り替える。 git checkout -b ○○○ 4, 一時保管していた内容を切り替えたブランチに適用する。 git stash apply
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プルリクエストでコンフリクトが発生した際の対処法

そもそもコンフリクトとは? 直訳すると「衝突」という意味。 ファイル上で「自分の作業」と「他人の作業」が重複してしまった状態のことを指す。   発生原因 「同一ファイル」の「同一箇所」を複数人が編集した状態でマージした時に発生する。 また、ローカルブランチをpushした後にmasterブランチに変更を加えてしまうことでも発生する。   git pull –rebase を使った対処法 <手順> 1, masterブランチを最新にして、作業ブランチをチェックアウト $ git checkout master $ git fetch origin $ git pull origin master $ git checkout [作業ブランチ] 2, 作業ブランチに対してmasterブランチをrebaseする $ git pull --rebase origin master 3, コンフリクトがあれば直す error: Failed to merge in the changes. #このようなエラーが発生したらコンフリクトなので対象ファイルを修正 #対象のファイルを開くと、コンフリクト起こした部分は以下のように表示される <<<<<<< HEAD [作業ブランチでの変更内容] ... ======= [マージしたブランチでの変更内容] ... >>>>>>> develop コンフリクトが発生しなくなるまで上記手順を繰り返す。   git pull origin master実行時にコンフリクトした時の対処法 <原因> ローカルブランチをpushした後にmasterブランチに変更を加えてしまうことで、origin/master(リモートリポジトリ)とmaster(ローカルリポジトリ)の状態に差異が生じてしまっていること。 <対処法> 現在のブランチの状態を「強制的に」他のブランチの状態に合わせるときの方法として、git reset --hard を利用する。 $ git reset --hard origin/master # 現在のブランチの状態をorigin/masterに合わせる ⚠️ git reset --hardを実行すると手元にある作業ツリーとインデックスの変更内容は、すべてふっとんで消えてなくなるので、バックアップを取るなどして実行前は注意する必要がある。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

保守運用の際に既存メソッドの定義場所を調べるメソッド[Ruby, Rails]

想定 既存のアプリの改修を担当することになった 独自に定義されているメソッドについて、どこで定義されているか知りたい 結論 メソッドがどこで定義されているか調べるメソッド method("メソッド名").source_location #=> ["/Users/user_name/dir1/dir2/app/helpers/application_helper.rb", 78] # これが定義場所 使い方 このメソッドは、binding.pryを用いたデバッグ中やrailsコンソール時などに用いることが可能です。(恐らく 以下では、binding.pryを用いたデバッグを用いて、メソッドの定義場所を調査しています app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> : </head> <body> <%= flash_messages %> <% binding.pry %> <%= yield %> <%= javascript_include_tag 'application' %> </body> </html> サーバー内にて Frame number: 0/114 From: /Users/user_name/dir1/dir2/app/views/layouts/application.html.erb:209 207: <%= flash_messages %> 208: <% binding.pry %> => 209: <%= yield %> 210: <%= javascript_include_tag 'application' %> 211: [1] pry(#<#<Class:xxxxxxxxxxxxxx>>)> method("flash_messages").source_location => ["/Users/user_name/dir1/dir2/app/helpers/application_helper.rb", 78] 参考 さいごに 参考記事では、'x'.method(:blank?).source_locationでメソッドの定義場所を調査されていますが、自分の環境ではうまく動作しませんでした。 また、自分が紹介したmethod("メソッド名").source_locationでは、アプリ内で定義されているメソッド以外を調査することはできませんでした。(なんでだろう? 余談ですが… 久しぶりの投稿になります。現在インターンとして、実務開発に参加してから1カ月が経ちます。 初めての開発現場はとても学びが多いですが、全然アウトプットの時間を確保できていませんでした… これからは、自分の中でのアウトプットに対する敷居を下げ、誰に向けた記事なのか意識することで、少しずつアウトプットの時間を確保しようと思います! 最後までお読み頂き、ありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsのアクションについて

基本的事項の復習。 1. Railsにおける7つのアクション アクション 役割 HTTPメソッド index リソースの一覧を表示する get new リソースの新規作成 get create リソースを新規作成して保存する post show 記録されたリソースの詳細表示 get edit リソースの編集 get update リソースの更新 patch/post delete リソースの削除 delete 2. newとsaveの違い newのコマンドはリソースの生成のみを行うので、このままではDBに反映するにはsaveのコマンドの実行も必要になる。 createは生成して保存を行うため、イメージとしてはnew+saveというアクション。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】rails s するとA server is already running.が発生する

はじめに 表題の通りですが、rails sするとA server is already running.となってしまい、serverが立ち上がりませんでした。 $rails s => Booting Puma => Rails 6.0.4 application starting in development => Run `rails server --help` for more startup options A server is already running. Check /home/ec2-user/environment/all-mng/tmp/pids/server.pid. Exiting 解決策 logに出てました。 A server is already running. Check /home/ec2-user/environment/all-mng/tmp/pids/server.pid. となっているので、 server.pidを一度削除して、rails sすると解決しました。 参考記事 A server is already running 対処方法【Rails】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

共同開発

インターン生で共同開発をしようという提案が通り、レシピを投稿する簡単なサービスを開発しました。共同開発したサービスの概要、過程、利用したツール等についてまとめていきます。 メンバー 僕を含めた3人(特に分野を決めていませんでしたが、結果的に僕が開発、他2人が設計中心になりました。「特に苦労したこと」) サービス概要 Food Frofessor レシピを投稿し、編集、お気に入り登録、コメントができる基本的なサービスです。 特に苦労したことの経緯や、「共同開発」を経験するといった目的が理由でそこまでハイレベルなサービスにしませんでした。 URL: https://food-professor.herokuapp.com/top (初回のみデータの読み込みに時間がかかります) GitHub: https://github.com/akira-iguchi/FoodProfessor-Backend / https://github.com/akira-iguchi/FoodProfessor-Frontend 使用技術 React (React Hooks, React Router) TypeScript Tailwind CSS Ruby 2.6.6 Rails 6.1.32 MySQL 8.0.23 Heroku Docker/docker-compose Figma Notion drawio VScode 機能一覧 ユーザー機能 ユーザーの新規登録 プロフィール画像の追加 ユーザー情報の編集 レシピ一覧 人気のレシピ トップ3 早くできるレシピ トップ3 最近追加したレシピ レシピ投稿機能 材料、手順を複数追加可能 関連するタグ追加可能 お気に入り機能 レシピのお気に入り登録、解除 お気に入りしたレシピの一覧 検索機能 レシピ名をキーワードに検索 関連するタグ、材料から検索 コメント機能 レシピのコメントの投稿、削除 コメントの一覧 ER図 Notionでタスク管理、設計 Notionという有名なタスク管理ツールでAPI設計、ミーティングメモ、重要な情報等を保存し、タスクを管理しました。 FigmaでUI設計 メンバーの方にFigmaというこれまた有名なデザインツールでUI設計していただき、それを元にFigma to Codeというプラグインで実装していきました(個人的に、このプラグインはそれほど使えなかった)。 環境構築 docker-composeでサービス(rails、react、mysql)をつくろうとしましたが、なんやかんやで1週間以上経過。最終的に1人がdocker-composeファイルをフロントとサーバーサイドで分けて別々で構築したいと提案し(そうじゃないとややこしくてできないと主張)、フロントとサーバーサイドのフォルダに分けて構築しました。 git管理 Fork→cloneしたリポジトリがFork元を追跡するようにし、オリジナルのリモートリポジトリに変更を及ぼすことなく変更をテストすることができるようにしました。 設定方法 ①GitHubから開発したいリポジトリ(オリジナルのプロジェクトのrepo)のページへ飛び、Forkボタンを押します。 ②Forkしたリポジトリ(組織じゃなくて自分のアカウントのレポジトリ)からcloneします。 git clone git@github.com:user_name/app_name.git ③ここで git remote -vを打ってローカルにcloneしたレポジトリがどのように関連づけられているか確認します。 ここで、オリジナルの方がoriginになってたらオリジナルのmasterを変更してしまうことになるので、originのURLを変える必要があります(おそらくそうなってたらOriginalの方からcloneしています)。 $ git remote -v // Forkしたリポジトリのみがoriginとして表示されます origin git@github.com:user_name/app_name.git (fetch) origin git@github.com:user_name/app_name.git (push) // もしOriginalの方をoriginとして登録されていたら $ git remote set-url origin YOUR_FORK_REPO_URL ④Fork元のリポジトリをローカルのリポジトリに関連づけます(URLを追加する) $ git remote set-url upstream ORIGINAL_REPO_URL ⑤upstreamとしてURLが追加されているか確認 $ git remote -v origin git@github.com:user_name/app_name.git (fetch) origin git@github.com:user_name/app_name.git (push) upstream git@github.com:team/app_name.git (fetch) upstream git@github.com:team/app_name.git (push) ⑥(upstreamとしてOriginalのリポジトリをURLに登録した後) git fetch upstream でリモートにあるOriginalの最新の変更状態をローカルに持ってきます。 ⑦git merge upstream/master で、自分のいるローカルのブランチにOriginalのローカルリポジトリ(upstream)のmasterブランチの変更分を適用させます。 ⑧ローカルで開発を進める。 個人的おすすめは git add 前にOriginalの変更分をfetchしておくこと git stash → git fetch && merge → git stash apply → git add && commit && push ローカルのoriginリポジトリ(Fork先の個人用リポ)へpushを続けていれば、組織のOriginalブランチに影響を及ぼさず、個人レポジトリで開発進められます。 特に苦労したこと 設計、環境構築までは空いた時間ながらもメンバーと協力し合い順調に進んだのですが、開発を進めていくうちに就職活動等でメンバーの方々が忙しくなり、まともな開発時間を有するのは僕だけになりました。このとき僕も共同開発後の予定を立てており、1人で悠々と作業を進める時間はありませんでした。このままでは、計画も意味をなくし、共同開発が断念される恐れがありました。 どうやって乗り越えたか それでも何とかサービスを完成させてデプロイまで終わらせたいと考えた僕は、メンバーと話し合い、機能の削減、メンバーの必要最低限の作業などを提案し、その後の開発は僕が中心となって進めました。そして、実装したい機能を妥協しながらも、許容範囲の期間でデプロイまで終わらせることができました。 まとめ 設計やgit管理など、個人開発とは違った実務に近い良い経験ができました。また、ほぼ無知だった僕にNotionなどのツールや専門知識などをお教えくださり、メンバーには感謝の気持ちでいっぱいです。優秀なメンバーの方々に負けないようこれからも頑張っていこうと思います。 気がかりとしては、まともなissue管理ができなかったので、今後は複数人での開発に向けてissueの扱いを学んでおきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】PV数閲覧数機能(メモ)

やり方 まずGemfileにimpressionistを追記。 Gemfile gem 'impressionist' ターミナル $ bundle install 次にimpressionistテーブルを作成します。   ターミナル $ rails g impressionist マイグレーションファイルが生成されるのでrails db:migrateをします。 class CreateImpressionsTable < ActiveRecord::Migration[6.1] def self.up create_table :impressions, force: true do |t| t.string :impressionable_type t.integer :impressionable_id t.integer :user_id t.string :controller_name t.string :action_name t.string :view_name t.string :request_hash t.string :ip_address t.string :session_hash t.text :message t.text :referrer t.text :params t.timestamps end add_index :impressions, %i[impressionable_type message impressionable_id], name: 'impressionable_type_message_index', unique: false, length: { message: 255 } add_index :impressions, %i[impressionable_type impressionable_id request_hash], name: 'poly_request_index', unique: false add_index :impressions, %i[impressionable_type impressionable_id ip_address], name: 'poly_ip_index', unique: false add_index :impressions, %i[impressionable_type impressionable_id session_hash], name: 'poly_session_index', unique: false add_index :impressions, %i[controller_name action_name request_hash], name: 'controlleraction_request_index', unique: false add_index :impressions, %i[controller_name action_name ip_address], name: 'controlleraction_ip_index', unique: false add_index :impressions, %i[controller_name action_name session_hash], name: 'controlleraction_session_index', unique: false add_index :impressions, %i[impressionable_type impressionable_id params], name: 'poly_params_request_index', unique: false, length: { params: 255 } add_index :impressions, :user_id end def self.down drop_table :impressions end end ターミナル $ rails db:migrate 次にpostテーブルにカラムを追加する。 ターミナル $ rails g migration AddImpressionsCountToPosts impressions_count:integer マイグレーションファイルが生成されたら、defaurult: 0 を追記してrails db:migrateします。 class AddImpressionsCountToPosts < ActiveRecord::Migration[6.1] def change add_column :posts, :impressions_count, :integer, default: 0 end end ターミナル $ rails db:migrate postモデルにis_impressionable counter_cache: true追記していきます。 app/models/post.rb class Post < ApplicationRecord is_impressionable counter_cache: true postコントローラーに追記していきます。 aap/controllers/posts_controller.rb def show @post = Post.find(params[:id]) impressionist(@post, nil, unique: [:ip_address]) end 同じ人が何度か閲覧しても1PVのカウントになります。 ビューに記述。 app/views/show.html.erb <p><%= post.impressions_count %></p> これで閲覧数が表示されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsのカスタムバリデーション機能を使ってNGワード(不適切な内容)を防いでみる

NGワード機能を追加しようと考えていたところ、 あまり参考にできる記事が見つからなかったので、記事を書いてみました。 Qiitaで記事を書くのは初めてですので、拙い面もありますがご了承ください。 やりたいこと 不適切な言葉(下品な言葉など)を防ぎたい htmlタグやurl,連続した文字("あああああ"など)を防ぎたい やったこと 1. modelにカスタムバリデーションを定義する(非推奨) 2. カスタムバリデータクラスを作る(推奨) テーブル構成 テーブル名 カラム名 User name Micropost content Comment content 1,2共通の操作 ブラックリストの作成(好きなように定義してください。) config/blacklist.yml --- - 不適切な単語1 - 不適切な単語2 - 不適切な単語3 不適切な単語は.gitignoreに入れてgitに載せないようにしておきましょう。 .gitignore #以下を追加 /config/blacklist.yml 1. modelにカスタムバリデーションを定義する(非推奨) まず、CommentのcontentとMicropostのcontentにNGワード機能を付けたいと思い、以下のようにカスタムバリデーションを定義してみました。 app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def content_cannot_contain_blacklist_words #blacklist.ymlから不適切な言葉を読み取る blacklist = YAML.load_file('./config/blacklist.yml') #contentが空でなく、contentの中にblacklistの用語が含まれているかを追加 if content.present? && blacklist.any?{ |word| content.include?(word) } errors.add(:contain_blacklist_words, ": 不適切な言葉は使用できません") # エラー時「contain_blacklist_words : 不適切な言葉は使用できません」と表示される。 end end def content_cannot_contain_invalid_regex # same_character_regex: 連続する五文字以上の語("あああああ")などを防ぐ # url_regex: https(http)から始まるurlを防ぐ # html_regex: htmlタグを防ぐ # 正規表現のエスケープのため %r!正規表現!で囲む invalid_regex = { same_character_regex: %r!(.)\1{4,}!, url_regex: %r!https?://[\w/:%#\$&\?\(\)~\.=\+\-]+!, html_regex: %r!<(".*?"|'.*?'|[^'"])*?>!} # invalid_regexをkey,valueとして取り出しvalue.match?(content)で正規表現と一致しているかを調べる。 if content.present? && invalid_regex.any?{|key,value| value.match?(content)} errors.add(:contain_invalid_regex, ": 使うことのできない文字列が含まれています") end end end Micropost.rbにvalidateを追加(validationsと間違えないように) app/models/micropost.rb class Micropost < ApplicationRecord # 先ほどapplicationで定義した関数を追加 validate :content_cannot_contain_blacklist_words validate :content_cannot_contain_invalid_regex end Comment.rbにもvalidateを追加する app/models/comment.rb class Comment < ApplicationRecord # 先ほどapplicationで定義した関数を追加 validate :content_cannot_contain_blacklist_words validate :content_cannot_contain_invalid_regex end このやりかたでの問題点 contentにしか適用できていない(カラム名が変わると適用できない。例えばnameにvalidationを適応したい場合、content.present?の部分をname.present?などに変えたコードを用意しなければならないので、同じコードを繰り返してしまう。) validate :関数名 を何度も書かなければならない。 そもそもどのカラムに適用してるのかがわかりにくい(validates :content, ~ のように書きたい) 2. カスタムバリデータクラスを作る(推奨) 1の問題点を解決しようとするとカスタムバリデータクラスを作ればいいことを発見する この通りにやってみる Validatorの定義 まずapp/validators/[validator名].rbを作る。 今回はinvalid_words_validator.rbとした。 app/validators/invalid_words_validator.rb # InvalidWordsValidatorの部分は先ほど付けた名前をキャメルケースにしたものを使う。 class InvalidWordsValidator < ActiveModel::EachValidator # record : テーブル名のこと(Micripostとか) # attribute : カラム名(contentとか) # value : フォームに入力された値("おはよう","foobar"とか) def validate_each(record, attribute, value) # blacklist.ymlから不適切な言葉を読み取る blacklist = YAML.load_file('./config/blacklist.yml') # valueが空でないか、blacklistに入力された値が含まれているかを判断 if value.present? && blacklist.any?{ |word| value.include?(word) } # contain_blacklist_words "内容~"と出力したくなかったので第二引数を''としている。 #(あまりいい方法ではないかもしれません。) # :contain_blacklist_wordsはja.ymlなどに定義しておくとよい。 record.errors.add(:contain_blacklist_words,'') end # same_character_regex: 連続する五文字以上の語("あああああ")などを防ぐ # url_regex: https(http)から始まるurlを防ぐ # html_regex: htmlタグを防ぐ # 正規表現のエスケープのため %r!正規表現!で囲む invalid_regex = { same_character_regex: %r!(.)\1{4,}!, url_regex: %r!https?://[\w/:%#\$&\?\(\)~\.=\+\-]+!, html_regex: %r!<(".*?"|'.*?'|[^'"])*?>!} # invalid_regexをinvalid_key,invalid_valueとして取り出しinvalid_value.match?(value)で正規表現と一致しているかを調べる。 if value.present? && invalid_regex.any?{|invalid_key,invalid_value| invalid_value.match?(value)} record.errors.add(:contain_invalid_regex, '') end end end 適用したいモデルに以下を定義する。 今回は例としてuser.rbのnameに定義してみる。 app/models/user.rb # validates :カラム名,Validator定義した名前: true validates :name,invalid_words: true 以上です。お疲れさまでした。 参考にしたサイト  - Railsガイド Active Record バリデーション  - Rails tips: カスタムバリデータクラスを作る(翻訳)  - Railsアプリでイタズラ投稿(NGワード)と格闘してみた話  - コメント機能等で特定のワード(悪口など)を制限することは可能ですか?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】RSpec実行時に意図しないログが吐き出された

はじめに 今回の出来事に関しては具体的な原因の特定には至れておりません。 そのため、もし具体的な原因が知りたいという方にとっては参考にならない記事になっていること、予めご了承いただけますと幸いです。 環境 Ruby 2.6.5 Ruby on Rails 5.2.6 RSpec実行時に大量のログが出た オリジナルアプリの機能追加に伴い、RSpecでテストを実行したところ、以下の画像のように意図しないログが吐き出された。 どうやらbefore do ... endのブロック内に囲まれたテストデータが作成された時のログのようだ。 (大量のテストデータを作成していてお恥ずかしい限りです。) 画像は一つのdescribeブロック内のログであり、複数のdescribeブロックを作成してテストしている場合、毎回このログが出力されるので、どこまでテストが行われているのかわからないし、何より時間がかかりすぎて効率が悪い。 ※本来であれば以下のように結果が返ってくると思います。 ということで原因を探ってみました。 gemのrails_12factorが原因だった git logを遡ったり、どこのブランチからこんなことになってしまっているのか一つ一つみているうちに、RSpecの実行結果が期待通りのリポジトリ内ではgemのrails_12factorがインストールされていなかった。 ...そういえばHerokuにデプロイできなくて試しにインストールしていたことを忘れていた。 調べてみるとこのgem、最終リリース日が2014年10月14日であり、だいぶ古いgemであることがわかった。 参考(RubyGems.orgより) それに伊藤淳一さんもrails_12factorは使わない方が良いと仰られている。 伊藤淳一さんの記事(【初心者必見】RailsアプリをHerokuに公開するのにrails_12factorは不要) 伊藤淳一さんの記事にも書かれていることだが、メンテナンスが止まっており、かつ必要のないgemに関してはインストールすべきではないという良い教訓になった出来事でした。 そのためにも、 ・使おうとしているgemがどれほどの人が利用していて ・いつアップデートされて ・バグなどの報告はないか をきちんと調べる習慣をつけたいと思います。 もし原因がわかる方がいらっしゃたらコメントを頂けますと幸いです。 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む