- 投稿日:2022-02-23T20:50:57+09:00
【rails】機能削除等で不要なテーブルが出てきた時の対応
はじめに 不要な機能削除が発生した際に、その機能でしか使ってなかったようなテーブルがあった場合は原則削除したほうがよいと思う。不要なソースコードやテーブルが残っていると混乱を招くだけなので。(ただし、なにかしらの理由で残しておいたほうがいい場合を除く) ただし、いきなり削除すると問題があった時に面倒なので、いったんrenameしてアクセスできなくして、しばらく運用して問題なければdumpをとって削除する。万が一問題があったら元のテーブル名に戻す。 注意 プロジェクトごとにやり方があると思うので、あくまで参考程度にしてください。 手順 不要な機能の削除方法 不要な機能のソースコードを削除する 別の場所で共通で使っている部分がある場合があるので注意する 不要な機能の削除に関わるspecを削除する テーブルのrename codeを全検索して model が使われていないことを確認する テーブルをrenameするmigrationファイルを作成する no_more_use_<元のテーブル名>のような名前にすると、もう使わないテーブルってことがわかるのでよさそう。 https://engineering.mercari.com/blog/entry/2017-05-26-104104/ ローカルでrails db:migrateして、ローカルDBにrenameを反映する ローカルで動作確認する テストが通ることを確認する stagingデプロイして動作確認する 本番デプロイし問題がないか監視する 本番DB反映後、問題なかった場合 1ヶ月くらい運用してみて、問題がなさそうであれば念の為dumpをとってテーブルを削除する 本番DB反映後、renameによる問題が発生した場合 railsのmigration機能を使っている場合、本番DBではrails db:rollbackしないこと (migrationのstatusとの整合性など、色々ややこしいことになる) まず発生している問題が本当にrenameによるものかしっかり調査する。 問題の原因がrenameによるものであると決まった場合、developからfeatureブランチをきって、元のテーブル名に戻すmigrationファイルを作成する 問題が解決しているか確認する
- 投稿日:2022-02-23T19:26:09+09:00
bundle exec rspec実行時にSelenium::WebDriver::Chrome#driver_path= is deprecated.〜 エラーが発生した
bundle exec rspec実行時のエラー解決備忘録 エラー内容 RSpecでテストを実行使用とした際に、下記エラーが発生した。 $ bundle exec rspec2022-02-23 18:27:19 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead. 解決方法 Gemfileの記載内容を修正 gem 'chromedriver-helper' を削除 gem 'webdrivers' を追加し、bundle installを実行 再度bundle rspec test を実行し、無事テストが走った group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' gem 'webdrivers' end 所感 そもそも、WebDriverとは何かを知らなかったため、今回のエラーで新たな知識を得られる良い機会だったなと実感した。。。 参考
- 投稿日:2022-02-23T18:13:02+09:00
unknown attributeのエラー
簡易的なフリマアプリを作成中。 一通りコードも書き終えて、いざHerokuへデプロイ!! デプロイ後、挙動確認のため、ユーザー登録→商品登録→別ユーザーの登録→商品購入を試みるも、 We're sorry, but something went wrong.のエラー文が表示。 原因探究 何が悪いのかを調べるため、エラーログを確認。 ターミナル > heroku logs --tail すると下記のエラーログを発見。 ターミナル ActiveModel::UnknownAttributeError (unknown attribute 'item_id' for Order.): 意味を調べてみると、Oderモデルにitem_idがありません といった内容。 Heroku上でカラムの確認を行うため、下記を入力。 ターミナル > heroku run rails console > Order.new 結果、 ターミナル => #<Order:0x00007fedc8872950 id: nil, item_id: nil, created_at: nil, updated_at: nil, user_id: nil> ??? item_idはちゃんと反映されている,,, なのに、なぜエラーが? 結果 色々調べているうちに、一つの検証が生まれる。 「そうだ、再起動してみよう」 ターミナル heroku restart --app <アプリケーション名> 上記コマンドを実行。 すると、見事成功!! ??? なぜ上手くいったかわかりません笑 「エンジニアあるある」で再起動するとなぜか上手くいくという記事を読んだ事があったが、まさしくこの事か笑 もし原因がわかる方がいらっしゃいましたら、ぜひご教示頂きたいです。
- 投稿日:2022-02-23T17:43:19+09:00
Railsでjsonデータを返す
モデルを作成 まずは返却したいデータを作成したいのでモデルを作成する。 rails g model Task title:string body:string Rails consoleでデータを作成 モデルができたら実際のデータをRails consoleで作成する。 rails c Task.create(titile: "jsonデータを返す", body: "railsをapiとして使いたいのでデータをjson形式で返したい") controllerを作成する jsonデータを返すためのアクションを作成する準備としてコントローラを作成する。 rails g controller api/v1/tasks routes.rbの編集 リクエストが通るようにroutes.rbを編集する。 namespace 'api' do namespace 'v1' do resources :tasks end end controllerの設定 controller内でjsonデータを返せるように’respond_to’を使い’.json’と言うリクエストが来たときの処理を記述する。 class Task < ApplicationRecord def show @task = Task.find(params[:id]) respond_to do |format| format.json {render json: @task} # @taskの情報がjsonデータとして返る end end end アプリにリクエストを送る これでjsonデータが返るはずなのでcurlコマンドを使いクエストを送る。 % curl "localhost:3000/api/v1/tasks/1.json" 下記のデータが返って来ればOK {"id":1,"title":"jsonデータを返す","body":"railsをapiとして使いたいのでデータをjson形式で返したい","created_at":"2022-01-01T00:00:00.000Z","updated_at":"2022-01-01T00:00:00.00Z"}
- 投稿日:2022-02-23T17:06:01+09:00
Ruby returnで複数の値を返す
はじめに 学習記録アプリの開発中、グラフの作成のために1週間分の日付の取得する処理を、「今週」「最後に学習した日の週」「最後に学習した日の前週」の3つそれぞれ記載していました。Rubyでは、メソッドの戻り値を複数返すことができるということなので、3つの処理を1つにまとめていきたいと思います。 環境 rails 6.0.4.4 ruby 2.6.5 chart.js 2.8.0 複数の戻り値を返し方 returnの後にカンマで区切って返す値を記述します。 def calc(a, b) x = a + b y = a - b return x, y end a = 20 b = 15 x_1, y_1 = calc(a, b) puts x_1, y_1 このように、x_1とy_1の変数にそれぞれ値が入っています。 ターミナル. 35 5 ちなみに1つの変数に対して、複数の戻り値を代入すると、自動的に配列に変換されます。 正確には、データそのものが配列形式で入るのではなく、データの場所の情報が入り、配列と同じ記述で取り出せるようです。 現在の状況 今週分の日付を取得(週初めの日付、週終わりの日付、1週間分の日付、1週間分の日付のJSON形式、の4つを定義しています) textbook_controller.rb @b_date = Date.today.beginning_of_week @e_date = Date.today.end_of_week week_date = week_date_calc(@b_date, @e_date) @week_date = week_date.to_json.html_safe 最後に学習した日を含む週の日付を取得 textbook_controller.rb @tb_date = @max_date.beginning_of_week @te_date = @max_date.end_of_week week_date = week_date_calc(@tb_date, @te_date) @week_date = week_date.to_json.html_safe 上記週の1週間前の日付を取得 textbook_controller.rb @lb_date = @max_date.prev_week @le_date = @max_date.prev_week(:sunday) week_date = week_date_calc(@lb_date, @le_date) @week_date_l = week_date.to_json.html_safe 補足 @max_dateは学習記録テーブルで日付の最大値を代入しています。 week_date_calcメソッドは週初めと週終わりの日付を渡して、その間の日付をもつ配列を作成します。 textbook_controller.rb def week_date_calc(b_date, e_date) w_date = [] s_date = b_date while s_date <= e_date w_date << s_date s_date += 1 end w_date end メソッドを作成 日付を1つ渡して、週初めの日付、週終わりの日付、1週間分の日付、1週間分の日付のJSON形式、の4つのデータを返すメソッドを作成します。 textbook_controller.rb def week_date_set(search_date) b_date = search_date.beginning_of_week e_date = search_date.end_of_week week_date = week_date_calc(b_date, e_date) week_date_json = week_date.to_json.html_safe return b_date, e_date, week_date, week_date_json end 上記、メソッドを使用してコードを書き直していきます。 今週分の日付を取得 textbook_controller.rb @b_date, @e_date, week_date, @week_date = week_date_set(Date.today) 最後に学習した日を含む週の日付を取得 textbook_controller.rb @tb_date, @te_date, week_date, @week_date = week_date_set(@max_date) 上記週の1週間前の日付を取得 textbook_controller.rb @lb_date, @le_date, week_date, @week_date_l = week_date_set(@max_date.weeks_ago(1)) prev_weekメソッドでは前週の週初めを取得してしますので、weeks_agoメソッドに変更しました。 おわりに これでコードを直す前と同じ動作をするようになりました。 なお、終わった後に気づきましたが、週初めと週終わりの日付は、メソッドで作成した配列から取得すればよかったので、個別で作成する必要はなかったですね。なので、4つの戻り値を返していますが、実際は2つでよかったです。 参照 関数で複数の返り値を返す/関数の引数は値渡し ― コーディングミスを防ぐには?(2
- 投稿日:2022-02-23T16:25:12+09:00
【解決方法1】We're sorry, but something went wrong. If you are the application owner check the logs for more information.
【事象】 RailsTutorial第6版の7章。 herokuへのデプロイ後に本番環境を確認したところ、なぜか/signupへのリンクで下記エラーが発生。 「We're sorry, but something went wrong. If you are the application owner check the logs for more information. 」 開発環境では問題なく作動しているが本番環境の/signupへのリンクで何か問題が起きていることが発覚。 【やったこと】 下記コマンドでログを確認したところ、status=500の赤いテキストを発見。 heroku logs --tail 500エラーとはサーバーのエラーとなり、heroku側のエラー。 本番環境でマイグレーションしていないことに気づき、下記コマンドを実行。解決。 heroku run rails db:migrate
- 投稿日:2022-02-23T13:02:55+09:00
ActiveRecord::Enum
ActiveRecord::Enumとは? ActiveRecord::Enumとは列挙型、あるいはenum型と呼ばれるものでActiveRecordが提供するenum型は数字のカラムに対してプログラム上で扱える別名を与えるもの。 ActiveRecord::Enumを使う 例えば、あるモデルにそのモデルの状態(ステータス)を扱うカラムがあるとする。そのようなカラムがあった時にenumを利用するとカラムの値を数字として管理することができる。 class Task < ApplicationRecord enum status: { # statusと言うカラムの値をenumを使って表現する private: 0, draft: 1, published: 2, } end このようにすると、statusカラムの値を数字として扱うことができるようになる。 (文字列としても、シンボルとしても指定することができるようになる) enumで定義されたカラムの値を確認する enumを利用すると、データを参照するときにも利点がある ステータスの状態を確認するメソッドが提供される 一つ目の利点は、モデルのインスタンスに対してそのステータスの状態を確認するためのメソッドが提供されること。 task = Task.first task.published? # taskが公開済みかどうかを検証している => true enumを利用したscopeを使えるようになる 二つ目の利点は、enumで定義した値を利用したscopeを利用できるようになること。 tasks = Task.draft # statusがdraftとなっているtaskを抽出できるようになる(where(status: 'draft')と同じこと) enumの値を簡単に書き換える enumの値を書き換えるときは、 task = Task.first task.published! とする(末尾に’!’をつける)ことでそのインスタンスの値を書き換える(DBの値も更新する)ことができる。 その他のメソッド DBに保存されている実際の値を確認する ’before_type_cast’で実際の値を確認することができる。 task = task.first task.status_before_type_cast => 2 # 今回の場合、publishedのであれば2と表示される enumで定義されている値を確認する enumで定義したカラム名を複数形で呼び出すと定義されている値全てを確認することができる。 Task.statuses => {"private"=>0, "draft"=>1, "published"=>2}
- 投稿日:2022-02-23T00:52:08+09:00
herokuでPostgreSQLの本番データベースをリセット
railsチュートリアル10章で気になったのでメモ 手順 $ heroku pg:reset DATABASE ▸ WARNING: Destructive action ▸ postgresql-○×△-○×△ will lose all of its data ▸ ▸ To proceed, type データベースの名前? or re-run this ▸ command with --confirm データベースの名前? >ここにデータベースの名前?を入力する # データベース再構成 $ heroku run rails db:migrate
- 投稿日:2022-02-23T00:09:23+09:00
外部キーのテストコードが上手くいかない
簡易的なフリマアプリを作成中。 単体テストコードにて、エラーが発生。 下記ターミナル内のエラー内容。 ターミナル Failures: 1) OrderDelivery 購入者情報の保存 内容に問題がある場合 userが紐ついていなければ購入できない Failure/Error: expect(@order_delivery.errors.full_messages).to include( "" ) expected [] to include "" # ./spec/models/order_delivery_spec.rb:81:in `block (4 levels) in <top (required)>' 2) OrderDelivery 購入者情報の保存 内容に問題がある場合 itemが紐ついていなければ購入できない Failure/Error: expect(@order_delivery.errors.full_messages).to include( "Item must exist" ) expected [] to include "Item must exist" # ./spec/models/order_delivery_spec.rb:86:in `block (4 levels) in <top (required)>' order_deliveryモデルとuserモデル、itemモデルをそれぞれ外部キーとして設定しているが、なぜか紐ついていない様子。 (ローカルサーバーでは上手くいっているのに・・・) expected [] to include 上記のエラー文は過去にも見たことがある。その時はバリデーションで記述したエラーメッセージと、テストコードで記述したエラーメッセージの内容が異なっていた事が原因だった。 ("can't be blank" を "can't be blanc" とスペルミスしたことでエラーになった) 今までも他のアプリで外部キーのテストコードは何回もしたが、バリデーションにエラーメッセージを記述した覚えはない。 google先生に聞いてみても、期待する回答は返ってこなかった。 もしかしたら、変数が間違っている? 何度もコードを読み返すが、間違っている様子もない。 そんな時、ふと思い付く。 「あれ?そういえばimageも外部キーやでな?」 models/item.rb のコードを見ると、確かにアソシエーションの記述がある。 しかもその下にはバリデーションの記述まである。 物は試しで該当のコードに追記してみる。 models/order_delivery.rb class OrderDelivery include ActiveModel::Model attr_accessor :token attr_accessor :post_code, :address_id, :municipalities, :house_number, :building, :tel, :order_id, :user_id, :item_id with_options presence: true do validates :user_id # 追記 validates :item_id # 追記 validates :token validates :post_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "input correctly"} validates :municipalities # 以下省略 成功!! でもなんで? しっかりとカリキュラムに書いていました。 Formオブジェクトで実装したクラスはアソシエーションを定義することはできないため、バリデーションを行う事ができません。そのため、use_idに対してバリデーションを新たに設定します。 エラー解決に2時間かかりました・・・ 失敗は今しかできないと前向きに捉えて、明日からまた学習に励みます!