- 投稿日:2021-01-06T23:03:24+09:00
余計なクエリ数を減らしたい。counter_cacheの検討からcounter_cultureの導入まで。
起こっていた問題
Railsでインスタグラムを模したアプリを作っています。
データベース構造はこんな感じです。このアプリのトップページ(投稿一覧)でこんなメソットを実装していたところ、
- if post.images.count >= 2 - # 処理クエリがこんなことになってしまいました^^;
imagesのcountが大量に回っている...^^;
そういえば、Railsには
counter_cache
という機能がデフォルトであって、こういうときに役立つんだよ、と聞いたことがあったので、調べてみたのが今回の始まりです。なお、実行環境は以下の通りです。
Rails 5.2.3
Ruby 2.6.0
counter_cacheについて
まず、上記の問題を解決する手段として、
- counter_cache(Railsのデフォルトの機能)を使う
- counter_culture(gem)を使う
- ゴリゴリコードを書く
の3種類があることがわかりました。(3つ目は教えていただきました!ありがとうございます!!)
まず、Railsのデフォルトの機能の
counter_cache
なのですが、以下のように実装します。models/image.rbclass Image < ApplicationRecord belongs_to :post, counter_cache: true end従属している(belongs_to)がついている方のモデルに、
counter_cache: true
を記載します。models/post.rbclass Post < ApplicationRecord has_many :images endhas_manyの方のモデルはそのままなのですが、こちらには、
子テーブルの名前_count
というカラムを作ります。今回の場合はimages_count
というカラムをposts
テーブルに作ります。$ rails g migration AddColumnToPost images_count:integerこうすることで、
images_count
カラムには、postが持っているimageの数が記録される様になります。ビューでは、こんなふうに書けば、いちいち
images
テーブルを呼び出さずにクエリ数も減るはず...- if post.images_count >= 2 -# 処理...と、ここまで書いて気がついた。すでにpostのデータがある場合はどうすればいいんだ。。。
はい、
counter_cache
の弱点はまさにそれで、すでにposts
テーブルにデータがある場合、images_count
の値は自動更新されません。先人たちが色々苦労されて修正された様子も見つけたのですが、構造が謎すぎて自分には使いこなせそうにありませんでした。。。
そこで、さらに調べていく中で出会ったのが次に紹介する
counter_culture
です。counter_cache補足
なお、
counter_cache
については、デフォルトのカラム名を変更したりなど、色々なオプションがありましたので、詳しくはこちらをご覧ください。Railsガイド - 4.1.2.3 :counter_cache
counter_cultureについて
counter_culture
は上記のcounter_cache
の弱点も補強してくれるような高機能のgemです。▶︎公式ドキュメントはこちら
導入方法
gemfile・migration
導入方法は以下の通りです。まず、
Gemfile
に以下を記載しbundle install
します。Gemfilegem 'counter_culture'その後、以下のコマンドでマイグレーションを生成します。
$ rails generate counter_culture Post images_countこちらのコマンドの結果、以下のようなマイグレーションが作成されます。
XXXXXXXXXXXXXXX_add_images_count_to_posts.rbclass AddImagesCountToPosts < ActiveRecord::Migration[5.2] def self.up add_column :posts, :images_count, :integer, null: false, default: 0 end def self.down remove_column :posts, :images_count end end同様の構造を持つマイグレーションファイルであれば、必ずコマンドで作成しないといけない、というわけではないようです^^
rails db:migrate
します。model
モデルファイルには、それぞれ以下の様に記載します。
models/image.rbclass Image < ApplicationRecord belongs_to :post counter_culture :post endmodels/post.rbclass Post < ApplicationRecord has_many :images endその他
そして、すでに
posts
テーブルにたくさんデータがあるなどの場合、コンソールで以下の様に実行します。$ rails c pry(main)> Image.counter_culture_fix_countsこうすることで、
posts
テーブルのimages_count
のカラムの中身がアップデートされます。最後に、ビューでこの様に書けば...
- if post.images_count >= 2 -# 処理無事、クエリ数が減りました!!
補足・参考資料等
counter_culture
にはオプションが色々ある様でしたので、詳しく知りたい方は公式ドキュメントをご覧ください。また、今回参考にさせていただいた記事は以下の通りです。
その他・感想等
今回の実装前に、N+1問題も発生していたので、その解決方法も参考までにご共有いたします。
クエリ数を減らしたいが今年の目標の一つだったのですが、SQLをゴリゴリ勉強する前に、手早く減らせる方法が見つかってよかったです^^
今後は、SQLの勉強を頑張っていきたいです。
- 投稿日:2021-01-06T20:38:09+09:00
git push herokuし、herokuのURLを開くとMethod Not Allowedが出る問題
問題
git push herokuすると以下のような表示が出ますよね
ここの下から2行目を開くとMethod Not Allowedがでます。解決法
上の写真の下から2行目はgit用のファイルなので、remote:の後のURLを開きましょう。
リンクを確認せずに開くとこういうことになってしまいます。
気をつけましょう(戒め)ちなみに
このgitのリンクはデプロイ用のgit repositoryらしいです。
なんらかの問題があった場合の最終手段としてcloneしたりするのはいいらしいですが
正規の”オリジン”リポジトリとしては使用してはいけないそうです。
詳しくは以下のリンクを参照してください。参照
- 投稿日:2021-01-06T19:54:53+09:00
ニコニコ動画apiを使って埋もれてる面白い動画を発掘する
はじめに
- ニコニコが好きなので作ってみました。
背景
- ニコニコ動画のとりあえずマイリストの廃止で動画のマイリスト数が激減した
- マイリストは面白い動画を見分ける判断材料になっていたのでとても残念
- とりマイの代わりにできた「いいね」の数はなぜか非公開(意味がわからない)
- 良質な動画を発見する機会と材料がなくなった
概要
- ニコニコのスナップショットAPIを使って、動画のタグ検索を行い動画リストを作成する
- 埋もれている動画の基準として、"(コメント数+マイリスト数×100)/再生数"が60%以上で、かつ再生数が500以上の動画
- csvファイルにて出力
開発環境
- 言語
- ruby
検索例(一部)
"実況プレイ動画"タグで検索。
対象の投稿日時は、2020年1月から12月末まで。
全部で1053件の動画が抽出されました。
最後に
スナップショットapiは一度に取得できる動画の数が最大100でyoutubeDataAPIのようにnext_page_tokenがなく、大量のデータを取得するには指定した日付で1週間ごとのループ行ったが少し面倒だった。
とりあえずマイリストを消した運営の判断は本当に意味がわからないし、いいねも機能しているとは思えない。いいね数を開示するか、いいねとマイリストを合算した数を開示しないと、いいねをする理由にはならないと思う。(ユーザーがいいね機能を使う理由が今のところ存在しない。)
- 投稿日:2021-01-06T19:49:15+09:00
【circleCI】Rails6/mysql8のProjectを自動テスト&自動コードチェック
はじめに
久しぶりにyml職人していたら、circleCIの書き方を忘れてしまったので、備忘録として残します
折角なので冗長なymlをCircleCI Orbsでスッキリさせてみました
CircleCIで設定する環境と、実際にアプリを運用する環境をできるだけ合わせることがポイント
GithubでPull Requetを作成したら、masterにマージする前に自動でビルドされてテストやリンターが走ったら便利。前提
- Githubのアカウントをもっていること、既にRailsのプロジェクトがあること
- Rspec & Rubocopが設定済みであること
- Mysqlをつかった例を説明します
開発環境
- Rails6
- Mysql8
- Docker
- AWS ecs
config.ymlの設定
?全体はこんな感じ
・commitした時とmergeした時にRspec&RUbocopが走る
・mergeしたらecsに自動デプロイ.circleci/config.ymlversion: 2.1 orbs: ruby: circleci/ruby@1.1.2 aws-ecr: circleci/aws-ecr@6.7.0 aws-ecs: circleci/aws-ecs@1.1.0 jobs: test: docker: - image: circleci/ruby:2.6.3 environment: RAILS_ENV: test RAILS_MASTER_KEY: ${RAILS_MASTER_KEY} DB_HOST: 127.0.0.1 DB_USERNAME: 'test_user' DB_PASSWORD: 'password' - image: circleci/mysql:8.0 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_DATABASE: app_test MYSQL_USER: test_user MYSQL_PASSWORD: password MYSQL_HOST: 127.0.0.1 TZ: "Asia/Tokyo" steps: - checkout - ruby/install-deps - run: name: Wait for DB command: dockerize -wait tcp://127.0.0.1:3306 -timeout 1m - run: name: Database setup command: bundle exec rails db:schema:load --trace - ruby/rubocop-check - ruby/rspec-test workflows: test: jobs: - test deploy: jobs: - aws-ecr/build-and-push-image: account-url: AWS_ECR_ACCOUNT_URL region: AWS_REGION aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY create-repo: true dockerfile: ./docker/api/Dockerfile repo: sample-repo tag: "${CIRCLE_SHA1}" filters: branches: only: master - aws-ecs/deploy-service-update: requires: - aws-ecr/build-and-push-image family: 'sample-task' cluster-name: '${ECS_ARN}' service-name: 'sample-api' container-image-name-updates: "container=sample-container,tag=${CIRCLE_SHA1}"
circleci/ruby@1.1.2
を使って諸々設定?公式に詳しいことが載ってます
circleci/ruby@1.1.2について: circleCIDeveloperorbsorbs: ruby: circleci/ruby@1.1.2今回使っているコマンド# gemのインストール - ruby/install-deps # Install gems with Bundler. # rubocopのcommand - ruby/rubocop-check # Check the code by Rubocop. You have to add `gem 'rubocop'` to your Gemfile. Enable parallelism on CircleCI for faster checking. # rspecのcommand - ruby/rspec-test # Test with RSpec. You have to add `gem 'rspec_junit_formatter'` to your Gemfile. Enable parallelism on CircleCI for faster testing.
circleci/aws-ecr@6.7.0
circleci/aws-ecs@1.1.0
を使って諸々設定?公式に詳しいことが載ってます
circleci/aws-ecrについて: circleCIDeveloper
circleci/aws-ecsについて: circleCIDeveloperorbsorbs: aws-ecr: circleci/aws-ecr@6.7.0 aws-ecs: circleci/aws-ecs@1.1.0今回使っているコマンド&ジョブ# 必要に応じてAWS CLIをインストールし、設定を行う。Amazon ECRにログインし、イメージをリポジトリにプッシュする。AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYの環境変数が必要です - aws-ecr/build-and-push-image: # Install AWS CLI, if needed, and configure. Log into Amazon ECR and push image to repository. Requires environment variables for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. We recommend these be saved in a Project # プロジェクトのデプロイ&ローリングアップデート - aws-ecs/deploy-service-update: # Update an ECS service.? jobsはtestだけ記述(今回はtest stepのみ記述下が、必要に応じてbuild stepも追加)
- プロジェクトに合わせてimageを選択
- それぞれ環境変数を設定
- database.ymlも環境変数を参照するように設定
jobsdocker: - image: circleci/ruby:2.6.3 # projectに合わせる environment: RAILS_ENV: test RAILS_MASTER_KEY: ${RAILS_MASTER_KEY} # circleCIのEnvironment Variablesにmaster.keyを追加しておく DB_HOST: 127.0.0.1 # defaultでlocalhostなのでmysqlに合わせる DB_USERNAME: 'test_user' DB_PASSWORD: 'password' - image: circleci/mysql:8.0 # projectに合わせる command: --default-authentication-plugin=mysql_native_password # v8から認証の方法が変わった為 commandで認証する environment: MYSQL_DATABASE: app_test MYSQL_USER: test_user # rootでは作成できない為、適当に定義する MYSQL_PASSWORD: password MYSQL_HOST: 127.0.0.1 # containerのhostを指定 TZ: "Asia/Tokyo"?
step
でcommand
を実行
サービス起動まで待機:dockerize を使って他のコンテナ内サービス起動を待つstepssteps: - checkout - ruby/install-deps - run: name: Wait for DB command: dockerize -wait tcp://127.0.0.1:3306 -timeout 1m # dockerize を使って他のコンテナ内サービス起動を待つ - run: name: Database setup command: bundle exec rails db:schema:load --trace # migration - ruby/rubocop-check - ruby/rspec-testあとはtestのjobsに先ほど設定したtestを指定して自動でテスト&コードチェックが実行される
workflowsworkflows: test: jobs: - test? masterにmergeされたらDockerイメージをECRにpushする
- circleCIにAWSの環境変数をそれぞれ設定
deploy: jobs: - aws-ecr/build-and-push-image: account-url: AWS_ECR_ACCOUNT_URL region: AWS_REGION aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY create-repo: true dockerfile: ./docker/api/Dockerfile # pushしたいDockerfileを選択 repo: sample-repo # ecrのリポジトリ名を選択 tag: "${CIRCLE_SHA1}" filters: branches: only: master? masterにmergeされたらデプロイ&ローリングアップデート
- circleCIにAWSの環境変数をそれぞれ設定
deploy- aws-ecs/deploy-service-update: requires: - aws-ecr/build-and-push-image family: 'sample-task' # ecsのタスク名 cluster-name: '${ECS_ARN}' # ecsのクラスター名 service-name: 'sample-api' # ecsのサービス名 container-image-name-updates: "container=sample-container,tag=${CIRCLE_SHA1}" # sample-containerの部分を適宜コンテナ名に変更?コミットしてみて動くか検証
- 投稿日:2021-01-06T14:02:54+09:00
【Rails】シングルテーブル継承を使って、テーブルの数を削減する【STI】
シングルテーブル継承(単一テーブル継承、STI)とは
シングルテーブル継承(以下、STI)は、単一の継承階層に所属するクラス群を、ただひとつのテーブルを使って永続化する手法です。
言葉だけでは伝わリにくいので、下図を御覧ください。
Postsテーブル(スーパークラス)が、サブクラスに継承する形になります。
しかし、注意点が2点あります。
- Books,Clothes,Goodsテーブルは実際には存在しない。
- 個々のデータは全てスーパークラスのテーブルに保存されます。この場合はPostsテーブル。
それでは、STIはどういう場面で使えばいいのでしょうか。
STI継承しないと中間テーブルが再生産が起きる
自分はSTIの存在を知らずにアプリを作っており、下図のようになってしまいました。
・・・。
PostsテーブルとしてはBooksとClothesとGoodsの記事を作りたかったのですが。。。
それぞれのテーブルを作ってしまうことで、それぞれの中間テーブル(ここでは、Comments,Likes,Pickupテーブル)が再生産が起きてます。
機能自体はできましたが、ゴチャゴチャしすぎて保守的には最悪ですね・・・。
何より新機能をつける度に3つテーブルを用意する必要があり、骨が折れます?そこで!STIを使い、Postsクラスをサブクラスに継承させました!
以下の通りです。めっちゃスッキリしましたね!
(画像にはBooks,Clothes,Goodsはテーブルとして書いてありませんが、継承させています。)
これで保守がしやすく、新機能もつけやすくなりました!やり方(結論)
1. スーパークラスを作る
rails g model post
でマイグレーションファイルを作成し、テーブルの設定をします。migrate/〇〇_create_posts.rbclass CreatePosts < ActiveRecord::Migration[6.0] def change create_table :posts do |t| t.references :user,foreign_key: true #省略 t.string :type #typeカラムを作成します! t.timestamps end end endここで注意したいことは、typeカラムを作成することです。
この中に継承先のクラス名が入り、管理されます。2. それぞれのクラスを作成し、スーパークラスを継承させる
先程のファイルをマイグレーションしてできたモデルファイルを編集したものです。
models/post.rbclass Post < ApplicationRecord belongs_to :user #省略 endそれでは
rails g model book --parent=Post
でbookモデルを作成します。
--parent=PARENT
オプションを使うことで、マイグレーションファイルを生成せずに済みます。models/book.rbclass Book < Post #こうすることでスーパークラスのアソシエーションやバリデーションが引き継がれます。 end完成です!
ちなみに!
この状態でBookモデルを保存すると、Postsテーブルのtypeカラムに"Book"が代入された状態で,Postsテーブルに保存されます。Book.create(title: "本です",.......)以上でSTIのやり方は終わりです。
最後まで読んで頂きありがとうございました!参考
Railsガイド
https://railsguides.jp/association_basics.html[Rails] STI(単一テーブル継承)とメタプログラミングでDRY
https://qiita.com/kidach1/items/789c2e7aebbcfbd2583e
- 投稿日:2021-01-06T09:48:16+09:00
[Gem不要!!HTML&CSSのみ]初心者が簡単にドロップダウンメニューを作成する方法
はじめに
ハンバーガーメニューやドロップダウンメニューの作成をしたいけど、Gem導入の方法がよくわからない・JavaScriptは思うようにいかない。
そんな初心者の方におすすめの記事なっております。開発環境
・Rails6.0.0
・MySQL5.6.50ドロップダウンメニューの実装
早速ドロップダウンメニューの実装の方法の流れを解説します。
ちなみにドロップダウンメニューとは以下のようなメニューのことです。「...」 を押すとメニューが表示されるものです。
よく見かけますが、JavaScriptでやるには面倒だし、Bootstrap導入のためにGemやjQueryを導入したりするのは初心者には中々ハードルが高めかなと思います。
それでは解説していきます。
1)application.html.erbで初期設定
まず
app/views/layouts/application.html.erb
でBootstrap
など必要なものを読み込みます。以下は僕がドロップダウンメニューを作成した際に使用したHTMLコードです。
views/layouts/application.html.erb<!DOCTYPE html> <html> <head> <title>PlansApp</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css"> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet"> # ここでbootstrapを読み込んでいます <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <%= yield %> # 以下の3行のscriptタグを追記しHTMLで使用できるようにしています <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html>初期設定はこれで終了です。
2)HTMLを書く
初期設定ができたら、早速ドロップダウンメニューのHTMLを記述していきます。
具体的には公式を見てもらってアレンジしてもらうのがベストですが、参考にした記事のものと、僕が作成したものを紹介しておきます。参考記事の例<nav class="navbar navbar-expand-lg navbar-light bg-light"> <a class="navbar-brand" href="#">Navbar</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Dropdown </a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="#">Action</a> <a class="dropdown-item" href="#">Another action</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="#">Something else here</a> </div> </li> <li class="nav-item"> <a class="nav-link disabled" href="#">Disabled</a> </li> </ul> <form class="form-inline my-2 my-lg-0"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> </div> </nav>僕の場合だと
listタグ
があるためレイアウトが崩れるなどの問題がありました。
そこで以下のようにアレンジいました。アレンジ例<a class="nav-link" href="#" id="navbarDropdown" role="button" datatoggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fas fa-ellipsis-h"></i> </a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="#">コメント履歴</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="#">フォローしているユーザー</a> <div class="dropdown-divider"></div> <%= link_to 'ログアウト', destroy_user_session_path, method: :delete, class: "dropdown-item" %> </div>僕の場合は
fontAwesome
でアイコンなどを使用したり、開発中のアプリのためパス指定があるところ・無いところがまばらですが、こんな感じでアレンジしました。3)CSSの適用させる
ここまでくれば、後はお好みでCSSを記述していくだけです。
参考までに以下に参考記事の記述例を紹介しておきます。参考記事のHTML7行目の以下のクラスに適用させていきます。
<div class="collapse navbar-collapse" id="navbarSupportedContent">なぜ、このクラスに適用させるのかの詳しい解説は参考記事をご覧いただけるとわかりやすいので、ぜひ見てみてください。
参考記事の例@media screen and (max-width: 992px) { .collapse.navbar-collapse{ padding: 10%; border-radius: 10px 10px 10px 10px; background: linear-gradient(white, #cccccc) !important; margin: 15%; font-size: 1.7rem; } } @media screen and (max-width: 992px) { // スマホ用 .collapsing.navbar-collapse{ padding: 10%; border-radius: 10px 10px 10px 10px; background: linear-gradient(white, #cccccc) !important; margin: 15%; font-size: 1.7rem; } }以上でドロップダウンメニューの実装は終了です。
これを期に、UI/UXのスキルの一部を見に付けてみてはいかがでしょうか。参考文献
- 投稿日:2021-01-06T09:19:27+09:00
rbenvでRubyのバージョンが切り替わらないときの対応
rbenvでRubyのバージョンが切り替わらなかったので、それのメモです。
事象
rbenvでバージョンを切り替えても変わりません
$ rbenv versions system 2.6.6 * 2.7.1 (set by RBENV_VERSION environment variable) $ rbenv global 2.6.6 $ rbenv versions system 2.6.6 * 2.7.1 (set by RBENV_VERSION environment variable)やったこと
set by RBENV_VERSION environment variable
と言われているのですが、特にどこにも書いていません。
また.zshrc
でexport RBENV_VERSION=2.6.6
をすると、rbenvのversionはうまく変更されますが、
rubyのバージョンを確認しようとするとエラーになります。$ rbenv versions system * 2.6.6 (set by RBENV_VERSION environment variable) 2.7.1 $ ruby -v /Users/naoto.koyama/.rbenv/versions/2.7.1/bin/ruby: invalid option -: (-h will show valid options) (RuntimeError)原因
Ruby 2.7の警告を抑制するために
.zshrc
に書いているRUBYOPTの設定を書いていることが原因でした$ cat ~/.zshrc ... export RUBYOPT='-W:no-deprecated -W:no-experimental' # <- これが原因上記を削除してから以下のコマンドを打てばOKです
$ unset RUBYOPT $ rbenv global 2.6.6 $ rbenv versions system * 2.6.6 (set by /Users/naoto.koyama/workspace/portal/.ruby-version) 2.7.1 $ ruby -v ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-darwin20]参考
rbenvのrubyコマンドがすべて「invalid option -: (-h will show valid options) (RuntimeError)」それRUBYOPTが原因かも
- 投稿日:2021-01-06T08:44:39+09:00
Rails6でvue.jsを使った開発を行うための設定に挑戦
Rails x Vue.jsを用いた開発に挑戦している。手探りなので間違っている箇所もあるかもしれないが自分なりに検索してやってみた。そういう記事としてご覧いただけると嬉しいです。
環境構築
①npmを導入(ホームディレクトリでOK)
brew install npm
②npmのパッケージをアプリに導入(アプリのディレクトリで)
npm init
ここで対話プロンプトが起動し、いくつか入力を求められる。()内はnpmコマンドがデフォルトで用意した値。
package name: (a) sample version: (1.0.0) 0.0.0 description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC)
name…packageの名前。ソースコードでimportやrequireをする際に使われる。
version…最初なので1.0.0とか0.0.0とかで答えておく。更新するたびにバージョンを変える必要あり
description…パッケージの説明。特に入力しないと以下のように表示される
"description": "This README would normally document whatever steps are necessary to get the application up and running.",アプリを使うための説明はREADMEに書いたから見てくれや〜って感じのこと言ってる
main…モジュールの中で最初に呼ばれるスクリプトファイル。パッケージをrequireした際に最初に呼ばれるファイル。今回はmain.jsとした。
test command…コマンドを使ってソースコードの実行ができるようにする設定。何も入力せずenterを押すと
"test": "echo \"Error: no test specified\" && exit 1"こんな感じの値が保存される。
これは
npm testというコマンドに対してecho以下の出力を出しますよ、という意味。実際に実行すると
% npm test > アプリ名@0.1.0 test > echo "Error: no test specified" && exit 1 ここ Error: no test specified npm ERR! Test failed. See above for more details.こんな感じでechoのところが出力される。
repository…紐付けるgitリポジトリを指定。.gitが存在している場合特に入力していなくても勝手に現在紐付いているgitリポジトリのurl入力される。
author…パッケージの著作者。
license…パッケージの権利情報。標準ではISCとなっているのでそれに倣った。
対話シェルで入力していないものも含めて最終的に以下のようなpackage.jsonができた。
{ "name": アプリ名, "private": true, (公開したくない場合true) "dependencies": { "@rails/actioncable": "^6.0.0-alpha", "@rails/activestorage": "^6.0.0-alpha", "@rails/ujs": "^6.0.0-alpha", "@rails/webpacker": "4.3.0", "turbolinks": "^5.2.0", "vue": "^2.6.12" }, "version": "0.1.0", "devDependencies": { "vue-loader": "^15.9.6", "webpack": "^5.11.1", "webpack-dev-server": "^3.11.1" }, "description": "This README would normally document whatever steps are necessary to get the application up and running.", "main": "main.js", (パッケージを呼び出した時に最初に呼ばれるソースコード) "directories": { "lib": "lib", "test": "test" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": 紐付けているgitリポジトリ }, "author": 自分で設定した著作者, "license": "ISC", "bugs": { "url": リポジトリのissue }, "homepage": リポジトリ名のreadme }③webpack, vue-loaderを導入
#ローカルインストール npm install webpack vue-loader --save-dev npm install vue --save #グローバルインストール npm install webpack -gこれらをインストールするとnode.jsのモジュールがnode_modulesフォルダに大量にインストールされるが、これらはpackage.jsonに依存関係が記述されていることで勝手に読み込んでくれる。よってgitにpushする必要がない。
なのでgitignoreをいじる
node_modules/こうするとnode_modulesがgitにpushされなくなる。
【参考】
vue.jsを用いた開発の導入
https://qiita.com/m0a/items/34df129d6d8991ebbf86
node_modulesをgitignoreに含める理由とか
https://qiita.com/growsic/items/b2965c0ba3b0aaae1ff8
package.jsonの中身
https://qiita.com/dondoko-susumu/items/cf252bd6494412ed7847
npmコマンドでpermission deniedされたので参照したやつ
https://qiita.com/okohs/items/ced3c3de30af1035242d
vue-loaderってなに
https://vue-loader-v14.vuejs.org/ja/
【次やること】
package.jsonの細かい設定の修正
- 投稿日:2021-01-06T00:29:16+09:00
【Rails × Docker】*エラー* Could not find gem 'mysql2 (~> 0.5)' in any of the gem sources listed in your Gemfile.
◆目的
ずっと悩んでいたDockerの課題解決に一歩近ずけたので忘却録のため、記述します!
*補足
私の場合、mysql2がないよ!というエラーが出た際、無理くり手動でmysql2を入れてみました。ですが、Gemfileのmysqlの次に記述されてるpumaがないですよ!というエラーが出たので、別の方法を探していたところwebpackerにたどり着きました。◆結論
コンテナ上で「rails webpacker:install」このコマンドを打った後、
Gemfile.lockの中身を削除して、
docker-compose up --build コマンドを打ったらコンテナが起動しました^^root@c9fe1cb41fda:/app2# rails webpacker:installエラー文
docker run コマンドを入力
mysql2がgemのどのリストを探してもないとエラーがでる。
↓↓↓
Could not find gem 'mysql2 (~> 0.5)' in any of the gem sources listed in your Gemfile.
Runbundle install
to install missing gems.*初回のbuildで docker build . ではなく docker-compose コマンドでimageを作成するべきだったのかも...
ユーザー名noMBP:app2 ユーザー名$ docker run -it -v /Users/ユーザー名/Desktop/app2:/app2 -p 3000:3000 f5dc18466a56 bash root@c1f90c58d633:/app2# rails new . --force --database=mysql --skip-bundle 〜 省略 〜 create storage create storage/.keep create tmp/storage create tmp/storage/.keep remove config/initializers/cors.rb remove config/initializers/new_framework_defaults_6_1.rb rails webpacker:install Could not find gem 'mysql2 (~> 0.5)' in any of the gem sources listed in your Gemfile. Run `bundle install` to install missing gems.仮説1 Gemfileにmysqlの記述がないのかもしれない。
catコマンドでGemfileの中身を確認
↓↓↓
Gemfileに gem 'mysql2', '~> 0.5' が存在している。git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.7.2' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.1.0' # Use mysql as the database for Active Record gem 'mysql2', '~> 0.5' # Use Puma as the app server gem 'puma', '~> 5.0' 〜 省略 〜仮説2 webpackerに問題があるのではないか。
webpackerインストールの直後にエラーが出ているため、webpackerに問題があるのではないか。
コンテナでrails sしてみるとwebpackerのエラーが出ていてwebpackerを入れてねと言われていることがわかる。
Webpacker configuration file not found /app2/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /app2/config/webpacker.yml (RuntimeError)root@c9fe1cb41fda:/app2# rails s => Booting Puma => Rails 6.1.0 application starting in development => Run `bin/rails server --help` for more startup options Exiting Traceback (most recent call last): 〜 省略 〜 2: from /usr/local/bundle/gems/webpacker-5.2.1/lib/webpacker/configuration.rb:92:in `data' 1: from /usr/local/bundle/gems/webpacker-5.2.1/lib/webpacker/configuration.rb:95:in `load' /usr/local/bundle/gems/webpacker-5.2.1/lib/webpacker/configuration.rb:99:in `rescue in load': Webpacker configuration file not found /app2/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /app2/config/webpacker.yml (RuntimeError)app2の中を確認→webpacker.ymlがない。
調べるとRails6以降はデフォルトでwebpackerが入っているということだったが、
なかったので、試行錯誤して入れてみることにした。①Dockerfileへ記述してもう一度 build してみる「apt-get install -y webpacker'」
E: Unable to locate package webpacker
ERROR: Service 'web' failed to build : The command '/bin/sh -c apt-get install -y webpacker' returned a non-zero code: 100ユーザー名noMBP:app2 ユーザー名$ docker-compose up --build Building web Step 1/24 : FROM ruby:2.7 ---> 7e58098089a4 Step 2/24 : ENV BUNDLER_VERSION=2.1.4 〜 省略 〜 Step 11/24 : RUN apt-get install -y webpacker ---> Running in 283d9d5a7034 Reading package lists... Building dependency tree... Reading state information... E: Unable to locate package webpacker ERROR: Service 'web' failed to build : The command '/bin/sh -c apt-get install -y webpacker' returned a non-zero code: 100②コンテナの中で以下のコマンドを実行
root@c9fe1cb41fda:/app2# rails webpacker:installDone in 153.13s.
Webpacker successfully installed ? ?成功!!
Gemfile.lockの中身を削除して docker-compose up --build を実行
無事に起動!!
web_1 | => Booting Puma web_1 | => Rails 6.1.0 application starting in development web_1 | => Run `bin/rails server --help` for more startup options web_1 | Puma starting in single mode... web_1 | * Puma version: 5.1.1 (ruby 2.7.2-p137) ("At Your Service") web_1 | * Min threads: 5 web_1 | * Max threads: 5 web_1 | * Environment: development web_1 | * PID: 1 web_1 | * Listening on http://0.0.0.0:3000 web_1 | Use Ctrl-C to stopまとめ
根本的な解決には至ってないですが、なんとかコンテナを起動させることができました。
1. docker runした際、なぜWebpackerがインストールされずmysqlのエラーが出たのか。
2. 直接コンテナでコマンドを打つことで起動させることができたが、次回起動時問題ないのか上記2点引き続き調べていきたいと思います。