20210730のRubyに関する記事は18件です。

Rails×Reactアプリをクローンした後の環境構築について。

Rails×Reactで構成されたアプリケーションに対して git clone した後、環境構築しようとした際に、ものすごく時間がかかったので、同じミスをしないようにメモしておく。 結論 ()は必要に応じて ① Nodeのバージョンを指定 (② .nvmrcに希望のバージョンを指定) (③ .gitignoreに .nvmrcを追加) ④ gemfile.lock削除 ⑤ Railsのバージョンを指定 ⑥ Bundle install ⑦ Rails db:create ⑧ Rails db:migrate ⑨ npm ci ⑩ yarn -v(→ yarnがインストールされていなければ yarn install) ( rails webpacker:compile) ①について まずlatestなNodeを使用するとnode-gypのエラーが後々発生する可能性があるので、出来ればstableなバージョンをインストールして使用するべき。 (npmは基本自動で変更されるので合わせる必要なし) ②について 筆者は、Nodeバージョン管理にnvmを使用していたので以下のHPを参考にした。 引用:https://shinshin86.hateblo.jp/entry/2020/05/14/220149 ③について 今後gitでマージする際に、.nvmrcファイルをアップロードしないように、以下のソースコードをプロジェクト内の.gitignoreファイルに追加。 .gitignore /.nvmrc ④について 基本的にGemfile.lockを削除することは、基本的にNG。 だが、筆者がクローンしたプロジェクトは、mimemagic <= 0.3.5に依存しているRailsアプリであったため、どうしても⑤のbundle installに失敗してしまっていた。 以下のHP上での、「都合によりRailsをアップデートできない・したくない場合の操作」を実行しても、どうしても上手くいかなかったため、 ④→⑤の流れをするとなぜか上手くいった。 引用:https://hackmd.io/@mametter/mimemagic-info-ja ⑤について Gemfileにrailsのバージョンを指定。 ⑨について npm ciとは。 package-lock.json から依存関係をインストールするコマンド。 既に node_modules フォルダの中身があっても一旦削除してくれる。 依存関係の更新をせずに整合性チェックと依存パッケージのダウンロードのみを行い、 npm install より高速に動作し、CIで必要なことだけを行うのが、このコマンドである。 nodeを使用しているプロジェクトをgit cloneするときは、必ず必要になるコマンド 引用:https://qiita.com/mstssk/items/8759c71f328cab802670 ⑩について ローカルでサーバーを開いたときに、 ℹ 「wdm」: wait until bundle finished: / ...... などが出てきてフロント画面の描画が遅い時などは、このコマンドが必要になる場合がある。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新規RailsプロジェクトをHerokuでデプロイするまでに最低限やることリスト12つ

はじめに RailsでアプリをつくってサクっとHerokuで公開するときに、とりあえずコピペでやっとくといいかもなリストです。 自分用の備忘録なので「あれもやったほうがいい!」とかはご容赦ください。 新しくRailsプロジェクトをつくる rails new <プロジェクト名> GitHubで履歴管理する 1. GitHubに新規リポジトリを作って接続 2. 空コミットする # リポジトリ作成 git init # 最初のコミット(空コミット) git commit --allow-empty -m "first commit" SQLiteからPostgresに変更 Rails6からコマンド1発ででいるようになったらしい。神。 #postgresqlに変更 rails db:system:change --to=postgresql # データベースをつくる createdb "dbname" # データベースの作成を完了させる rails db:create GemfileにGemを追加 自分がよく使うのはこんな感じ # for debug gem 'pry' # for design gem 'bootstrap' # use jQuery gem 'jquery-rails' gem 'jquery-turbolinks' # use font-awesome gem 'font-awesome-sass' # ogpの取得 gem 'open_uri_redirections' gem 'opengraph_parser' gem 'solargraph' # サイトマップを作る gem 'sitemap_generator' # sitemap自動更新用 gem 'whenever', require: false # 日本語対応 gem 'rails-i18n' # Slack通知(ユーザーからの投稿などがある場合は、Slack通知で不正なデータがないかチェック) gem 'slack-notifier' # Sentryでエラー検知 gem 'sentry-raven' # Kaminariでページング gem 'kaminari' bundle install jQueryを使えるようにする npm install --save jquery yarn install --check-files webpackをインストール rails webpacker:install サービスの根幹をつくる ・モデル作成 rails g model <モデル名> ・マイグレーションでカラム作成 rails g migration AddColumnTo<モデル名> rails db:migrate ・コントローラー作成 rails g controller <コントローラー名> ・ルーティング設定 config/routes.rb Rails.application.routes.draw do root 'results#index' # 存在しないページはトップページに飛ばす(これ最後に書かないとそこ以降は全部これに引っかかってとばされる…) get '*unmatched_route', to: 'results#index' end ・Viewのデザイン設定 集客、拡散させるためのコツ 画像の作成 ・Twitter用のカードをつくってassets/images配下に置く ・iPhoneでホーム画面に追加されるとき用のアイコン(apple-touch-icon.png)をつくってassets/images配下に置く ・faviconをつくってassets/images配下に置く ページのタイトル、説明、ogp画像を可変にする ・application helperで管理 app/views/layouts/application.html.erb <meta name="description" content="<%= page_description %>"> <meta property="og:title" content="<%= page_title %>"> <meta property="og:description" content="<%= page_description %>"> <meta property="og:url" content="<%= request.url %>"> <meta property="og:image" content="<%= page_image %>"> <meta name="twitter:card" content="summary_large_image"> <meta property="twitter:card" content="summary_large_image"> <meta name="twitter:image" content="<%= page_image %>"> app/helpers/application_helper.rb module ApplicationHelper def page_title title = "基本のタイトル" title = @page_title + " - " + title if @page_title title end def page_description description = "基本の説明" if @work description = "#{変数}と組み合わせたり" end description = @page_description.nil? ? description : @page_description end def page_image image = asset_url('基本のサムネイル')   # ページごとにサムネイルがあったら上書き if @works @works.each do |work| unless work&.thumbnail_url.blank? || work.nil? image = work&.thumbnail_url break end end end image end def get_twitter_card_info(page) twitter_card = {}   # ページごとにTwitterシェア時のサムネイルを変える if page twitter_card[:url] = page.url twitter_card[:title] = page.title twitter_card[:description] = page.description else twitter_card[:url] = '基本のURL' twitter_card[:title] = '基本のタイトル' twitter_card[:description] = '基本の説明' end twitter_card[:image] = asset_url('基本のサムネイル画像') twitter_card[:card] = 'summary_large_image' twitter_card[:site] = '@rubys8arks' twitter_card end end エラーページの作成 エラーメッセージの日本語化 locals配下にja.ymlを置く タイムゾーンの日本時間化 config/application.rb # デフォルトのタイムゾーンを日本にする config.time_zone = 'Tokyo' config.active_record.default_timezone = :local config.i18n.default_locale = :ja # デフォルトのlocaleを日本語(:ja)にする config.i18n.default_locale = :ja config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s] その他、サービス公開までにやること(任意) 独自ドメイン取得 Google Analytics取得 Google Tag Manager取得 お問い合わせ用のGoogleフォーム作成(お題箱などでも代用可) 利用規約作成 プライバシーポリシー作成 エラー検知用にSentryを繋ぐ Herokuにデプロイする railsのバージョン違いでエラーが起こったら Heroku上でデータベースをつくる heroku rake db:migrate Herokuの無料枠でのスリープ回避 UptimeRobotを使用する(回避できてるのかな?) ほかにもあったら追記してみます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新規RailsプロジェクトをHerokuでデプロイするまでに最低限やることリスト10つ

はじめに RailsでアプリをつくってサクっとHerokuで公開するときに、とりあえずコピペでやっとくといいかもなリストです。 自分用の備忘録なので「あれもやったほうがいい!」とかはご容赦ください。 新しくRailsプロジェクトをつくる rails new <プロジェクト名> GitHubで履歴管理する 1. GitHubに新規リポジトリを作って接続 2. 空コミットする # リポジトリ作成 git init # 最初のコミット(空コミット) git commit --allow-empty -m "first commit" SQLiteからPostgresに変更 Rails6からコマンド1発ででいるようになったらしい。神。 #postgresqlに変更 rails db:system:change --to=postgresql # データベースをつくる createdb "dbname" # データベースの作成を完了させる rails db:create GemfileにGemを追加 自分がよく使うのはこんな感じ # for debug gem 'pry' # for design gem 'bootstrap' # use jQuery gem 'jquery-rails' gem 'jquery-turbolinks' # use font-awesome gem 'font-awesome-sass' # ogpの取得 gem 'open_uri_redirections' gem 'opengraph_parser' gem 'solargraph' # サイトマップを作る gem 'sitemap_generator' # sitemap自動更新用 gem 'whenever', require: false # 日本語対応 gem 'rails-i18n' # Slack通知(ユーザーからの投稿などがある場合は、Slack通知で不正なデータがないかチェック) gem 'slack-notifier' # Sentryでエラー検知 gem 'sentry-raven' # Kaminariでページング gem 'kaminari' bundle install jQueryを使えるようにする npm install --save jquery yarn install --check-files webpackをインストール rails webpacker:install サービスの根幹をつくる ・モデル作成 rails g model <モデル名> ・マイグレーションでカラム作成 rails g migration AddColumnTo<モデル名> rails db:migrate ・コントローラー作成 rails g controller <コントローラー名> ・ルーティング設定 config/routes.rb Rails.application.routes.draw do root 'results#index' # 存在しないページはトップページに飛ばす(これ最後に書かないとそこ以降は全部これに引っかかってとばされる…) get '*unmatched_route', to: 'results#index' end ・Viewのデザイン設定 集客、拡散させるためのコツ 画像の作成 ・Twitter用のカードをつくってassets/images配下に置く ・iPhoneでホーム画面に追加されるとき用のアイコン(apple-touch-icon.png)をつくってassets/images配下に置く ・faviconをつくってassets/images配下に置く ページのタイトル、説明、ogp画像を可変にする ・application helperで管理 app/views/layouts/application.html.erb <meta name="description" content="<%= page_description %>"> <meta property="og:title" content="<%= page_title %>"> <meta property="og:description" content="<%= page_description %>"> <meta property="og:url" content="<%= request.url %>"> <meta property="og:image" content="<%= page_image %>"> <meta name="twitter:card" content="summary_large_image"> <meta property="twitter:card" content="summary_large_image"> <meta name="twitter:image" content="<%= page_image %>"> app/helpers/application_helper.rb module ApplicationHelper def page_title title = "基本のタイトル" title = @page_title + " - " + title if @page_title title end def page_description description = "基本の説明" if @work description = "#{変数}と組み合わせたり" end description = @page_description.nil? ? description : @page_description end def page_image image = asset_url('基本のサムネイル')   # ページごとにサムネイルがあったら上書き if @works @works.each do |work| unless work&.thumbnail_url.blank? || work.nil? image = work&.thumbnail_url break end end end image end def get_twitter_card_info(page) twitter_card = {}   # ページごとにTwitterシェア時のサムネイルを変える if page twitter_card[:url] = page.url twitter_card[:title] = page.title twitter_card[:description] = page.description else twitter_card[:url] = '基本のURL' twitter_card[:title] = '基本のタイトル' twitter_card[:description] = '基本の説明' end twitter_card[:image] = asset_url('基本のサムネイル画像') twitter_card[:card] = 'summary_large_image' twitter_card[:site] = '@rubys8arks' twitter_card end end 日本にローカライズ エラーメッセージの日本語化 locals配下にja.ymlを置く タイムゾーンの日本時間化 config/application.rb # デフォルトのタイムゾーンを日本にする config.time_zone = 'Tokyo' config.active_record.default_timezone = :local config.i18n.default_locale = :ja # デフォルトのlocaleを日本語(:ja)にする config.i18n.default_locale = :ja config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s] エラーが起きたときのページを日本語化 public配下の404.html、422.html、500.htmlの中身を変える その他、サービス公開までにやること(任意) 独自ドメイン取得 Google Analytics取得 Google Tag Manager取得 お問い合わせ用のGoogleフォーム作成(お題箱などでも代用可) 利用規約作成 プライバシーポリシー作成 エラー検知用にSentryを繋ぐ Herokuにデプロイする railsのバージョン違いでエラーが起こったら Heroku上でデータベースをつくる heroku rake db:migrate Herokuの無料枠でのスリープ回避 UptimeRobotを使用する(回避できてるのかな?) ほかにもあったら追記してみます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActiveRecordから任意のカラムだけ抜き出す【Ruby】【Rails】

忘れそうな(というか一度忘れた)のでメモ <Model> .<Query Interface> .pluck(:<Culumn1>, :<Culumn2>, ...) .map {|<Culumn1>, <Culumn2>, ...| {<Culumn1>: <Culumn1>, <Culumn1>: <Culumn2>, ...}} 例: User id name desc 1 a This is a 2 b This is b User .find(1) .pluck(:name, :desc) .map {|n, d| {name: n, desc: d}} #=> [{name: "a", desc: "This is a"}]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SlackのIncoming Webhooksを試してみた

やりたいこと SlackのIncoming Webhooks経由でメッセージを送る。 作業ログ SlackのIncoming Webhooksを設定 Slackのドキュメントを参考に設定する。 Slack appの作成 ドキュメントのCreate your Slack appボタンを押下 今回は、From scratchの方を試す。 appの名前と、紐付けるworkspaceを指定し、Create Appを押下する。 Incoming Webhooksの設定 以下Webページにリダイレクトされるので、Incoming Webhooksを押下する。 以下ページでActivate Incoming WebhooksのトグルをOnにする。 Webhook URLs for Your Workspace設定が表示されるので、Add New Webhook to Workspaceボタンを押下する。 以下ページに遷移するので、通知を送るチャンネルを指定して、許可するを押下する。 以下画像のように、Webhook URLが作成された。 curlでメッセージをPOSTしてみる $ export SLACK_WEBHOOK_URL=<Webhook URL> $ curl -X POST -H "Content-type: application/json" --data "{'text':'Hello, World!'}" $SLACK_WEBHOOK_URL ok Slackのチャンネルを確認 メッセージの送信ができた!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[エラー]こんなミスは嫌だ

はじめに 本記事では、これまでに学習した中で、 ヒューマンエラー、ケアレスミスをしてしまったことを紹介いたします。 私としても、同じことを繰り返さないために、備忘録としてここに記述します。 ケアレスミス resources 例 (正) resources :prototypes resources :prototypes do resources :comments, only: :create end resources :users, only: :show (誤) resources :prototypes resources :prototypes do resources :comments, only: :create resources :users, only: :show end usersまでネストしていたため、 Prefixも異なる事態に陥りました。 モデル (正)model (誤)medel 見つけた時は、笑いが止まりませんでした。 locals 以前の記事にも、載せましたが、 (誤)local (正)locals です。 img src (誤)img scr (正)img src eachメソッド 例 (正) <% @prototype.comments.each do |comment| %> (誤) <%= @prototype.comments.each do |comment| %> =をつけるととんでもないぐらいブラウザに情報が飛び交う。 何に=をつけるのか、つけないのか正確に理解する必要があります。 終了タグの抜け そのままの意味です。 アソシエーション (正) belongs_to :user has_one_attached :image has_many :comments , dependent: :destroy (誤) belong_to :user has_one_attached :image has_many :comment , dependent: :destroy 「s」抜け。見つけることは困難を極めます。 render (正) if prototype.save redirect_to prototype_path else render :edit end (誤) if prototype.save redirect_to prototype_path else render_to :edit end redirect_toに引っ張られないように。 7つのアクション new・・・新規投稿ページを表示 create・・・データの投稿を行う *逆にしない!! 終わり キリがないので、 これで終わりにします。 とにかくミスが発覚した時は、 例えケアレスだからと言って軽く扱わず、 間違えたことをアウトプットし、なぜ間違えたのかフィードバックを行うよう心がけましょう。 引き続き頑張ります!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby HTTPClientでpostする

簡単なことなんだけどbodyを入れるのがうまくいかず詰まったのでメモ require 'httpclient' require 'json' client ||= ::HTTPClient.new # body を jsonにする必要がある body = JSON.generate({ hoge: { moge: 1234 } }) # railsの場合は to_json で ok header = { 'Content-Type' => 'application/json' } client.post "https://example.com/api/hoge/moge", body: body, header: header ※こちらの記事は自ブログからの転載です
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rspec

初期設定 Rails で RSpecを利用する場合、一度だけ次のコマ ンドを実行する必要があります。 その結果、specディレクトリが作られて、その下に spec_helper.rb および rails_helper.rb というファイルが生成されます。 rails g rspec:install 使用方法 spec/models/_spec.rb require "rails_helper" RSpec.describe "User" do before do @user = build(:user) end it "すべての値が正しく入力されていれば登録できる" do expect(@user).to be_valid end it "nameがなければ登録できない" do @user.name = "" expect(@user).not_to be_valid end it "emailが存在しなければ登録できない" do user = build(:user, email: "") expect(user).not_to be_valid end it "emailが他のユーザーと重複したら登録できない" do user = build(:user, email: "test@test.com") tester = User.new(email: "test@test.com") expect(tester).not_to be_valid end it "password_digestが6文字以下の場合登録できない" do user = build(:user, password_digest: "cavaf") expect(user).not_to be_valid end end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]Capistranoで自動デプロイで気をつけたいこと

はじめに 前回、Capistranoによる自動デプロイを導入しましたが、その中で個人的に、コマンド一つ覚えていればいいかと勝手思っていましたが、自動デプロイする前にやるべきことがあります。 それを簡単に記事に残しておきます。 よろしくお願いします。 ローカルでVScodeを修正した場合 これは単純にアプリの改修や変更を行った場合、必ずリモートリポジトリにコミット、プッシュを行います。 もしブランチを切っている場合はmergeまで行います。 その後、一度プロセスをkillします。 例↓ まずはプロセスを確認します。 ターミナル [ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn 続いてプロセスをkill ターミナル # 上記の例だと「17877」 [ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill プロセス番号 そして最後にローカルのアプリディレクトリでbundle exec cap production deployを実行して完了。 ローカルでデータベース関連の内容を修正した場合 もしデータベース関連の修正を行った場合、まず本番環境で下記の二つのコマンドを実行します。 ※実行する際、「DISABLE_DATABASE_ENVIRONMENT_CHECK=1」というオプションが必要です。 ターミナル(本番環境) rails db:drop RAILS_ENV=production rails db:create RAILS_ENV=production その後、一度プロセスをkillします。 例↓ まずはプロセスを確認します。 ターミナル [ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn 続いてプロセスをkill ターミナル # 上記の例だと「17877」 [ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill プロセス番号 そして最後にローカルのアプリディレクトリでbundle exec cap production deployを実行して完了。 Nginxを修正した場合 Nginxの修正を行った場合は下記コマンドを実行します。  terminal:ターミナル sudo systemctl restart nginx 最後に Capistrano導入後、bundle exec cap production deployのコマンドさえ打てば自動デプロイしてくれると思っていましたが、もう一手間加えないといけなくて、私は少し失敗しました。 このような細かいところもしっかり身につけたいと感じました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】rails sのログに表示される「Cannot render console from <IPアドレス>!」とは何か?

はじめに dockerを使って、localhostで立ち上げたときに、rails server上で以下のようなログが発生。 web_1 |Cannot render console from 172.23.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1 結論 「docker のネットワークで使っているIPアドレス(172.23.0.1)がループバックの範囲(127.0.0.0~127.255.255.255)にないから、表示できないよ」 ↓ 「environment/development.rbに追記して、docker のネットワークで使っているIPアドレス(172.23.0.1)を許可しなければならないよ」 詳細 アウトラインはこちらの方の記事を参考に。 https://qiita.com/terufumi1122/items/73da039e6fc90ee0a63f ※補足「networks: 127.0.0.0/127.255.255.255」とは? 【ループバックアドレスの範囲】を指すようです。 ちなみに、「ループバックアドレス」とは自分自身を示す仮想的なIPアドレスです。 (例えば"localhost/3000" と "127.0.0.1/3000"はおおよそ等価と考えてよさそうです。) 「ループバックアドレスは一般的に127.0.0.1が指定されているけど、 状況次第で127.0.0.0~127.255.255.255の範囲で別のアドレスも設定できるよ」ということです。 詳しくは以下の記事で。 おわりに 簡単ですが、以上です。 どなたかの参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者向け】Rubyでコマンドラインツールを作る

hello.rb というファイルを作ってみてください 中身は puts "world" です これを ruby hello.rb で実行してみてください % ruby hello.rb world となりますね。 そうしたら #!/usr/bin/env ruby puts "world" に変更してくてみださい。 ファイル名も hello.rb から hello に変更します。 ./hello で実行してみましょう。 % ./hello -bash: ./hello: Permission denied このようなエラーが出ます。 実行する権限がないので追加します。 % chmod +x ./hello 再実行します。 % ./hello world おわりです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#3 sinatraでActiveRecordを使わずに掲示板アプリを作ってみた

前回の続き。 前回はモデルを見て行ったので、今回はdatabaseディレクトリ を見ていく! create_database.sql ここにデータベースやテーブル作成のSQLを書いてくっぽいけど、どんなコマンドを実行したら データベースが作られるのかは全く分からない。そこからイメージがついてない。 てか、ここにSQL文書いても、まずデータベースに接続ができるのかが怪しい。 確かにクライアントは定義したけど、別のディレクトリのファイルに定義したから それをどう連携させるのか。include db.rbとかするわけでもなさそうだし。 一旦、そこは飛ばしてどんなコードか理解していくとする CREATE DATABASE IF NOT EXISTS 0ch; まぁこれはそのままで、Ochって名前のデータベースがなければ、 そのデータベースを作るって感じです。 next! create_post.sql CREATE TABLE IF NOT EXISTS posts ( id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL, topic_id INTEGER UNSIGNED NOT NULL, name VARCHAR(255), email VARCHAR(255), body TEXT NOT NULL, created_at DATETIME NOT NULL, PRIMARY KEY (id) ); IDカラムのデータ型はINTEGERで数値が入っていく UNSIGNED AUTO_INCREMENT は、https://kin-memo.hatenablog.com/entry/2018/02/07/182952 この記事にある通りで UNSIGNEDは、正の数値のみ受け付ける感じ。 AUTO_INCREMENTはその名の通り。 レコードが追加されると、自動的に付与される。今回付与されるのはid レコードが追加されるたび、idカラムにインクリメントされた数値が追加されていく。 NOT NULLはその名の通り、このカラムには絶対何かしらの値が入っていなきゃいけない。といった制約。 topic_idがなぜあるかというと、 一つのトピックに、いくつもの投稿が紐ずくので、 どのトピックに対する投稿かを識別できるように、 外部キーを設定する必要がある。 https://www.dbonline.jp/mysql/table/index8.html PRIMARY KEY(主キー)とは作成したテーブルの中の1つまたは複数のカラムの組み合わせに対して設定するもので、テーブルに格納されているデータをに格納されているデータを識別するための目印のようなものです。 まぁ確かにプライマリーキーがあれば、id=3でそのデータが参照できるってわけか。 プライマリーキーに指定したカラムは重複とNULLを受け付けないようになる。 受け付けたら識別できなくなるからね てか、railsで開発してた頃は、プライマリキーを指定した覚えなんてないんだが、、 それなのに困ったことなかった。。。。なんでやねん。。。 sinatraとrailsを行き来すれば、理解深まりそうと思った。 railsの仕組みについても興味が湧いてきますね。 create_topics.sql CREATE TABLE IF NOT EXISTS topics ( id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY (id) ); まぁ、さっき解説した通りですね〜。 app.rb ついでにapp.rbも見ておきましょう。 require 'sinatra' require 'slim' require_relative 'models/topic' require_relative 'models/post' get '/' do @topics = Topic.all slim :index end post '/topics' do topic = Topic.new(title: params[:title]) topic.save redirect '/' end get '/topics/:id' do @topic = Topic.find(params[:id]) @posts = Post.of_topic(@topic.id) slim :show end post '/topics/:topic_id/posts' do name = params[:name].empty? ? '名無し' : params[:name] post = Post.new(name: name, email: params[:email], body: params[:body], topic_id: params[:topic_id]) post.save redirect back end なんだかroutes.rbみたい まぁ、なんとなくわかるので、大丈夫でしょう。 次回はいよいよ、アプリを実行していきたいと思います。 コードを書いたはいいけど、何のコマンドを打てば データベース作られたりするのかがいまいちよく分からないですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLに躓きすぎたので備忘録として残す

題名通り今回はMySQLで躓きすぎたので備忘録として、今後もしまた同じ目に遭ったとしても対処できるように備忘録として残す事にしました。 使用環境 Ubuntu : 18.04.3 LTS \n \l Rails : 6.1.3.2 MySQL : Ver 14.14 Distrib 5.7.34 Vagrant : 2.2.17 エラー内容 今回のエラーは、MySQLの環境構築の完了後マイグレーションしようとした時に出てきたエラーになっております。 結論 結論として、今回のエラーは「schema.rb」の環境がどうやら悪さをしていたみたいなので、今まで使用していた「schema.rb」を消して新しい「schema.rb」を作る事によって、無事MySQLのエラーをクリアすることができました。 エラー文の全容 マイグレーションしようとしたら出てきたエラー ターミナル $ rails db:migrate == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: you can't define an already defined column 'name'. /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:36:in `block in change' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ArgumentError: you can't define an already defined column 'name'. /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:36:in `block in change' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) まず「devise_create_users」の36行目と5行目のカラム'name'が二つありますよというエラー文になります。 ということはカラム'name'を消せば解決です。 2 rails db:migrate:statusでマイグレーションの状態を確認する ターミナル $ rails db:migrate:status database: hoge_development Status Migration ID Migration Name -------------------------------------------------- up 20200208124233 Create hoges down 20200209055424 Devise create users down 20200220052712 Add hoges tosees down 20201207042223 Add hoge to hoges down 20201210015310 Add user id to hoges down 20201222045544 Create hoges down 20210303012038 Add hoge to users down 20210714052813 Create hoges 一応、rails db:migrate:statusで確認をしてからカラム'name'を消しました。 (statusがdownだと手動で直すことができます) 3.再びrails db:migrateをする ターミナル $ rails db:migrate == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) -> 0.0673s -- add_index(:users, :email, {:unique=>true}) -> 0.0530s -- add_index(:users, :email, {:unique=>true}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Duplicate key name 'index_users_on_email' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:41:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Duplicate key name 'index_users_on_email' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:41:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Duplicate key name 'index_users_on_email' /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:41:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) 成功した!と思ったのも束の間、新たなエラーが、、、。 今度は、devise_create_users.rbの41行目とMySQLにエラー。。。 4.rails db:dropをしてみた devise_create_users.rbの41行目は直しても、MySQLかぁ。。。と思ったので、一度dropしてみました。 ターミナル $ rails db:drop rails aborted! ActiveRecord::NoEnvironmentInSchemaError: Environment data not found in the schema. To resolve this issue, run: bin/rails db:environment:set RAILS_ENV=development /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:drop => db:check_protected_environments (See full trace by running task with --trace) ※rails db:dropとは一度データベースを消すときに使います。 「bin/rails db:environment:set RAILS_ENV=development」というのが出ましたが、今はやめときました。 5.rails db:createしてみた ターミナル $ rails db:create Database 'hoge_development' already exists Database 'hoge_test' already exists 既に存在している模様 6.もう一度rails db:migrateしてみた ターミナル $ rails db:migrate == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Table 'users' already exists /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Table 'users' already exists /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Table 'users' already exists /vagrant/hoge/db/migrate/20200209055424_devise_create_users.rb:5:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) 若干変わったけど進展なし。。。 7.rails db:resetで実行 ターミナル $ rails db:reset rails aborted! ActiveRecord::NoEnvironmentInSchemaError: Environment data not found in the schema. To resolve this issue, run: bin/rails db:environment:set RAILS_ENV=development /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:drop => db:check_protected_environments (See full trace by running task with --trace) 実行できない。。。(泣) おのれschemaめ。。。 8. bin/rails db:environment:set RAILS_ENV=development ターミナル $ bin/rails db:environment:set RAILS_ENV=development vagrant@ubuntu-bionic:/vagrant/hoge$ お!いけるか! 9.rails db:reset ターミナル $ bin/rails db:environment:set RAILS_ENV=development vagrant@ubuntu-bionic:/vagrant/hoge$ rails db:reset Dropped database 'hoge_development' Dropped database 'hoge_test' Created database 'hoge_development' Created database 'hoge_test' rails aborted! ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `comments` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:setup => db:schema:load (See full trace by running task with --trace ...。 10. 念の為MySQLのバージョンを確認 ターミナル $ mysql --version mysql Ver 14.14 Distrib 5.7.34, for Linux (x86_64) using EditLine wrapper 11. rails db:migrate ターミナル $ rails db:migrate == 20200208124233 Createhoges: migrating ====================================== -- create_table(:hoges, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Mysql2::Error: Table 'hoges' already exists /vagrant/hoge/db/migrate/20200208124233_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::StatementInvalid: Mysql2::Error: Table 'hoges' already exists /vagrant/hoge/db/migrate/20200208124233_create_blogs.rb:3:in `change' /vagrant/hege/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Table 'blogs' already exists /vagrant/hoge/db/migrate/20200208124233_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) エラーの内容が変わりました。 MySQLの何かが悪さをしています。 12. rails db:reset ターミナル $ rails db:reset Dropped database 'hoge_development' Dropped database 'hoge_test' Created database 'hoge_development' Created database 'hoge_test' rails aborted! ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:setup => db:schema:load (See full trace by running task with --trace) どうやら一つはdatabase.ymlの入力がよろしくないようですね。 13.database.ymlを変更して再度rails db:reset ターミナル $ rails db:reset Dropped database 'hoge_development' Dropped database 'hoge_test' Created database 'hoge_development' Created database 'hoge_test' rails aborted! ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/schema.rb:57:in `block in <top (required)>' /vagrant/hoge/db/schema.rb:13:in `<top (required)>' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:reset => db:setup => db:schema:load (See full trace by running task with --trace) 変わらないな・・・。 最終手段でschemaを古いものを消して、新しくschemaを作る事にしました。 14. 一度まっさらな状態にして$ rails db:migrate:statusを見てみた ターミナル $ rails db:migrate:status Schema migrations table does not exist yet. 一応schemaファイルは無くなっていますね 15. schemaファイルを作り直してbin/rails db:migrate ターミナル $ bin/rails db:migrate == 20200208124233 Createhoges: migrating ====================================== -- create_table(:hoges, {}) -> 0.0566s == 20200208124233 Createhoges: migrated (0.0569s) ============================= == 20200209055424 DeviseCreateUsers: migrating ================================ -- create_table(:users, {}) -> 0.0592s -- add_index(:users, :email, {:unique=>true}) -> 0.0587s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0553s == 20200209055424 DeviseCreateUsers: migrated (0.1741s) ======================= == 20200220052712 AddBlogsTosees: migrating =================================== == 20200220052712 AddBlogsTosees: migrated (0.0000s) ========================== == 20201207042223 AddNameToBlogs: migrating =================================== -- add_column(:hoges, :name, :string) -> 0.1584s == 20201207042223 AddNameToHoges: migrated (0.1588s) ========================== == 20201210015310 AddUserIdToHoges: migrating ================================= -- add_column(:hoges, :user_id, :integer) -> 0.1395s == 20201210015310 AddUserIdToHoges: migrated (0.1397s) ======================== == 20201222045544 Createhoges: migrating =================================== -- create_table(:hoges, {}) rails aborted! StandardError: An error has occurred, all later migrations canceled: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/onsen/db/migrate/20201222045544_create_hoges.rb:3:in `change' /vagrant/onsen/bin/rails:9:in `<top (required)>' /vagrant/onsen/bin/spring:15:in `<top (required)>' Caused by: ActiveRecord::MismatchedForeignKey: Column `hoge_id` on table `hoges` does not match column `id` on `hoges`, which has type `bigint(20)`. To resolve this issue, change the type of the `hoge_id` column on `hoges` to be :bigint. (For example `t.bigint :hoge_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/migrate/20201222045544_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Caused by: Mysql2::Error: Cannot add foreign key constraint /vagrant/hoge/db/migrate/20201222045544_create_hoges.rb:3:in `change' /vagrant/hoge/bin/rails:9:in `<top (required)>' /vagrant/hoge/bin/spring:15:in `<top (required)>' Tasks: TOP => db:migrate (See full trace by running task with --trace) おしい・・・! どうやらhogesカラムのidをbigintに変えればいけそうな感じですね。 ※(t.bigint :hoge_id)に変えればよい 16.修正して再度bin/rails db:migrate ターミナル $ bin/rails db:migrate == 20201222045544 CreateHoges: migrating =================================== -- create_table(:hoges, {}) -> 0.0619s == 20201222045544 CreatHoges: migrated (0.0620s) ========================== == 20210303012038 AddProfileImageToUsers: migrating =========================== -- add_column(:users, :profile_image, :string) -> 0.1556s == 20210303012038 AddProfileImageToUsers: migrated (0.1557s) ================== == 20210714052813 CreateHoges: migrating ================================== -- create_table(:hoges) -> 0.0691s == 20210714052813 CreateHoges: migrated (0.0694s) ========================= 通った〜!! 疲れた。。。 MySQLは本当に面倒なので皆様も似たような現象がありましたら、「schema.rb」を見てみてください。 見てくださった皆様、お付き合いありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#2 SinatraでActiveRecordを使わずに掲示板アプリを作ってみた

前回rubyでSQL文発行して、データベースを操作するノリが分かってきたので、今回は これのコードリーディングをやっていきたいと思います。 (的外れな可能性大なので鵜呑みにしないでください。あくまで軽いメモ用です。。) モデルから見ていく models/db.rb require 'mysql2' class DB def self.query(sql) client.query(sql, symbolize_keys: true) end private def self.client @client ||= Mysql2::Client.new(host: 'localhost', username: 'root', database: '0ch') end end client.queryはなんか前回出てきたやつですね 前回は、client = Mysql2::Client.new(host: "localhost", username: "root", password: '', database: 'mysql') こんな感じで定義されていたと思います。 クライアント、いわゆるどこにどんなユーザー情報、パスワードでデータベース(MySQL)に接続するのかを提示します。 どんなクライアントかはまだ定義してないですね。 symbolize_keyはハッシュ のキーをシンボルにするメソッドらしい。(いやオプションかもしれん) なんでこれをつけなければいけないのかが全く分からない。 def self.client @client ||= Mysql2::Client.new(host: 'localhost', username: 'root', database: '0ch') end ここでどんなクライアントかを定義しますと んで、@clientの中身に何かあればそれ使って、なかったクライアントを新たに生成する的な。 ||=と書くことで、データベースへの問合せを最小限にしています。 とにかくクライアントを定義するメソッドと、クエリをデータベースに投げるメソッドがあるということです。理解度は全然ですが、とりあえず次。 models/post.rb なんだか投稿に関するモデルっぽいですね〜 require_relative 'application_entity' class Post < ApplicationEntity MIN_SIZE = 1 MAX_SIZE = 140 attr_reader :name, :email, :body, :topic_id, :id, :created_at def initialize(name: nil, email: nil, body:, topic_id:, id: nil, created_at: nil) @name, @email, @body, @topic_id, @id, @created_at = name, email, body, topic_id, id, created_at end def self.of_topic(topic_id) DB.query("SELECT * FROM posts WHERE topic_id = #{topic_id}").map { |hash| new(hash) } end def save validate DB.query("INSERT INTO posts (name, email, body, topic_id, created_at) VALUES ('#{@name}', '#{@email}', '#{@body}', '#{@topic_id}', NOW())") end def validate unless @body.size >= MIN_SIZE && @body.size <= MAX_SIZE raise Invalid, "本文は#{MIN_SIZE}文字以上、#{MAX_SIZE}文字以下で指定してください" end end end 'require_relative 'application_entity'は一旦置いといて、 attr_reader :name, :email, :body, :topic_id, :id, :created_at とはなんぞや。と、attr_accessorは知っとるけど、attr_readerは知らんぞと https://qiita.com/aberyotaro/items/626a88388d44802240a0 が分かりやすかったので、拝見してみた。 attr_readerはインスタンス変数の読み出し専用アクセサを定義できる。 はい、アクセサとはなんやねん。と インスタンス変数の値を読み書きするメソッドのこと。 Rubyはそのままではインスタンス変数にアクセスできない仕様になっています。 もっというとruby はclassの外からインスタンス変数を参照、再定義できないので、 それらをしようとしたときにアクセサメソッドが必要なのです。 今回は、参照するだけで、一度投稿した投稿は編集できない感じだと思うんで、 attr_readerなのでしょう これでpostの属性を一気に定義できる。便利やのう initializeメソッドで @name, @email, @body, @topic_id, @id, @created_at = name, email, body, topic_id, id, created_at で一気に定義できるのも初めて知った。  def self.of_topic(topic_id) DB.query("SELECT * FROM posts WHERE topic_id = #{topic_id}").map { |hash| new(hash) } end で、さっきのDBクラスのqueryメソッドを呼んでるって感じです。 こないだやった通り、生SQLが書いてありますね、訳してみると postsテーブルの全情報を取得、ただし条件はトピックidが◯のトピックの投稿だけを取得してきてねーー。 って感じですね。 topic_idがいつ、どの瞬間に入るのかがイメージできないですが、一旦次。 map { |hash| new(hash) } ですが、これはよくわらかなくて、取得した投稿全部をハッシュ化するのでしょうか、、、? なぜハッシュ化するのかよく分からないので、次。 って思ったのですが、単純に、取得したデータからインスタンスを生成してるだけでした。 なぜhashという変数名にしたのかは、あとで谷道さんに聞くことにしましょう。 考えてみれば、データベースから取得したデータをそのまま使えるわけではなく、 インスタンス化しないことには、ruby内でそのデータを使えないってわけですね。 railsではそんなことを意識せずともなんとなくアプリが作れてたので、 感動するとともに、そりゃ実力つかんわーー。とも思った。 アンチrailsになりそうな気持ちを沈めつつ次へ。 def save validate DB.query("INSERT INTO posts (name, email, body, topic_id, created_at) VALUES ('#{@name}', '#{@email}', '#{@body}', '#{@topic_id}', NOW())") end 最初にvalidateを呼び出していますが、validateメソッドは後々定義するから一旦飛ばして、 NOW()メソッドは、現在時刻を取得するMySQLのメソッドらしいです。 def validate unless @body.size >= MIN_SIZE && @body.size <= MAX_SIZE raise Invalid, "本文は#{MIN_SIZE}文字以上、#{MAX_SIZE}文字以下で指定してください" end end そして、肝心のvalidateメソッド raise Invalidってのが引っかかった。raiseは例外処理を発生させるメソッドらしいが、 Invalidが何やと。その答えは後々登場。 MIN_SIZE MAX_SIZEを変数にすることで後から、やっぱ最大文字数200文字で!って言われたときも変更に対応しやすいコードになってます。 こういった細かい工夫も注目しつつ次いきましょう。 models/topic.rb require_relative 'application_entity' class Topic < ApplicationEntity MIN_SIZE = 1 MAX_SIZE = 50 attr_reader :title, :id, :created_at, :updated_at def initialize(id: nil, title:, created_at: nil, updated_at: nil) @id, @title, @created_at, @updated_at = id, title, created_at, updated_at end def self.all DB.query('SELECT * FROM topics ORDER BY updated_at DESC').map { |hash| new(hash) } end def self.find(id) result = DB.query("SELECT * FROM topics WHERE id = #{id} LIMIT 1").first new(result) end def save validate DB.query("INSERT INTO topics (title, created_at, updated_at) VALUES ('#{@title}', NOW(), NOW())") end def validate unless @title.size >= MIN_SIZE && @title.size <= MAX_SIZE raise Invalid, "タイトルは#{MIN_SIZE}文字以上、#{MAX_SIZE}文字以下で指定してください" end end end てか、どのクラスもApplicationEntityを継承してるってことに今気づいた。 そのクラスも後々登場してきます。 result = DB.query("SELECT * FROM topics WHERE id = #{id} LIMIT 1").first .fitstがなぜあるのか、 配列の先頭の要素を返します。要素がなければ nil を返します と書いてあったが、なぜこのメソッドが必要なのかがイメージできてない。 取得したいデータがなかった場合にもエラーを起こさないためなのか。 未来の自分が解決してくれるだろう。 LIMIT 1は取得するデータの行数を制限。と書いてあった。 "行数"を制限という言い回しが気になるが、単純に取得するデータの個数を制限してるって感じでいいんすかね。 トピックがなぜ一個しか取得できない仕様なのかがよく分からない。 多分、トピックが被らないようにするため、、、?? まぁなんとなくイメージができたんで次。 application_entity.rb post.rbとtopic.rbの継承元となっていた、モデルですね。 require_relative 'db' class ApplicationEntity class Invalid < StandardError end end お、見覚えがあるInvalidが出てきた。 しかもStandardErrorを継承している。。。 Invalidクラスに何も書かないなら、raise Invalidとかじゃなくて、 railse StandardErrorでええやん。とか Post < StandardErrorでええやん。とか思ったりしてる。 なんでやねん。。。。調べてみると、、 StandardErrorのスーパークラス(親クラス)がExceptionらしい。 https://yarb.hatenadiary.org/entry/20121005/p1 https://qiita.com/kasei-san/items/75ad2bb384fdb7e05941 この記事出てきたが、rescueに関係ありそうなので、一旦置いといて、 raiseは、プログラムの中で意図的に例外(エラー)を発生させるときに使います。 と書いてあった。 んーー、でもなぜStandardErrorをInvalidに継承させる必要があるのかが、分かりませんねー。 二度手間やん。って初心者は思っちゃう。 まぁ、理解はそこそこに全体像をつかみたいので、今回はこんな感じで。 #3はこちら
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]Bootstrapでヘッダーを整える

今回は、Bootstrapを使ってヘッダーにハンバーガーメニューの導入を行っていきます。 ヘッダーを指定した画面幅に応じて、コンテンツを表示したり、三本線の画像(ハンバーガーメニュー)を表示したりを切り替えていきます。 開発環境 ruby 2.6.3 Rails 5.2.6 Bootstrap 4.5 前提 前提として、Bootstrapの導入が行われている状態で説明していきます。 いきなり完成形 まずは、こんなことをして〜、の前にいきなり完成形のコードをのせておきます。 header <header class="sticky-top"> <nav class="navbar navbar-expand-md navbar-dark bg-dark text-white"> <a> <%= link_to 'Top', root_path, data: {"turbolinks" => false} %> </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNavDropdown"> <ul class="navbar-nav ml-auto"> <% if user_signed_in? %> <li class="nav-item"> <%= link_to '投稿フォーム', new_post_path %> </li> <li class="nav-item"> <%= link_to '投稿一覧', posts_path %> </li> <li class="nav-item"> <%= link_to 'ランキング', ranks_rank_path %> </li> <li class="nav-item"> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> </li> <% else %> <li class="nav-item"> <%= link_to "新規登録", new_user_registration_path %> </li> <li class="nav-item"> <%= link_to "ログイン", new_user_session_path %> </li> <% end %> </ul> </div> </nav> </header> これだけで、あとはよろしく〜では、雑すぎるので、解説していきます。 ヘッダーを固定 header <header class="sticky-top"> : まず、ヘッダーを画面上部に固定します。 classにsticky-topをつけるだけで、上部に固定できます。(Bootstrap優秀〜) ブレークポイントの指定 header <!--ブレークポイントの指定--> <nav class="navbar navbar-expand-md"> : わかりにくいので、背景色、色の指定等の記述は削除しています。 navbar-expand-mdで、mdでナビゲーションバーとハンバーガーメニューの切り替えを行います。 ハンバーガーメニュー部分 ハンバーガーメニューアイコンの設置と開いたり閉じたりの処理を行っています。 header <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNavDropdown"> : #navbarNavDropdownを対象に開閉を行っていきます。 「navbar-toggler」classが付与される要素にdata-toggle="collapse"、data-target="#[id名]"、aria-controls="[id名]"、aria-expanded="false"、aria-label="Toggle navigation" まとめ ハンバーガーメニューの実装がかんたんに実装できました。 Bootstrap日本語リファレンスにも説明がありますので、ぜひ調べてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sinatraでActiveRecordを使わずに掲示板アプリを作ってみた

プロローグ Rails今までやってきて、あまり基礎力というか、地力ついた感じしないんすけど、何やったらいいすかねーーー。。。ってruby-jpに相談したら、 https://github.com/ttanimichi/0ch#sinatra%E3%81%A7%E6%8E%B2%E7%A4%BA%E6%9D%BF%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86 この課題に取り組んでみてください。 とアドバイスをいって頂いた。 この課題を見てみると、ActiveRecordを使わずに、生SQLを書いて掲示板アプリを作るという指定があった。 そんなことやったことがないので、早速詰んだ。 def save validate DB.query("INSERT INTO posts (name, email, body, topic_id, created_at) VALUES ('#{@name}', '#{@email}', '#{@body}', '#{@topic_id}', NOW())") end 多分だけど、この生SQLを書けば、ActiveRecord使わずとも、データベースとやり取りができそう。 ActiveRecordのsaveメソッドがそこら辺をよしなにやってくれてたと思うと、そりゃ実力付かんわ。 と改めて反省。 何はともあれ、ActiveRecordを使わずにデータベースを操作する練習をしなきゃならんので、 https://qiita.com/toshiro3/items/b65b2ad744d8f3ecc734 この記事をやってみることに。 この記事通りだとうまく行かないことあるので、 補足させていただくと まず、CREATE DATABASE test; を実行しないと、 create table test.languages (id int, name varchar(32)); これでエラー出るようです。 CHAR 型は指定した文字数以下の文字を格納した場合には文字列の末尾に空白を必要なだけ付け加えて指定の長さの文字列として格納します。ただし値を取得する場合は末尾にある空白は全て削除された上で取得されます。比較される時も同じです。 VARCHAR 型は末尾に空白を付けるようなことはしません。また現行のバージョンでは末尾に空白がある文字列であっても空白が付いたまま格納されます。取得する時も空白付きで取得しますが、 WHERE 句で比較する時だけ末尾の空白を削除した上で比較されます。 引数には、最大文字列を指定してるっぽい。 https://www.dbonline.jp/mysql/type/index3.html 引用 require 'mysql2' client = Mysql2::Client.new(:host => 'localhost', :user => 'root', :password => 'password') query = %q{select user, host from test.languages} results = client.query(query) results.each do |row| puts "--------------------" row.each do |key, value| puts "#{key} => #{value}" end end これだとエラー出るので、 require 'mysql2' query = %q{select * from test.languages} に変更。 てか、require 'mysql2' って書いた時点で、mysql使えるのはしゅごい。 Macにmysqlをインストールしたからなのは分かってるけど。。。。 そこら辺を上手いこと参照してくれるのは驚き。 将来の成長した自分が、そこら辺の疑問点を解決してくれることを願って、先に進めよう。 あと %q{}って記法がよく分からないので、調べてみると https://qiita.com/mogulla3/items/46bb876391be07921743 シングルクオートやダブルクオートのエスケープが不要になる。 うん、意味が分からん。 https://blog.senseshare.jp/escape.html を参考にして説明すると、 エスケープ処理とは、プログラムの中で使う特殊な記号を「ただの文字」として扱いたい時に行う処理です。 とありました。なるほど、なるほど。 次回はいよいよ https://github.com/ttanimichi/0ch#sinatra%E3%81%A7%E6%8E%B2%E7%A4%BA%E6%9D%BF%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86 この課題のコードリーディングで基礎力や地力をつけていきたいと思います。 #2はこちらから
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

わくちんわくちんしたかったお話

前置き 以前巷でNKDICEって流行りましたよね?それに応じてqiitaでも類似の内容が結構出ましたが今回の記事は今更それです。ダイスを振ってワクチンって出したい感じのコードを書いていきたいと思います。 やってみよう 確かNKDICEは6面ダイスだった気がするのでそれっぽいのをまず作ります。 DICE = { 1 => 'わ', 2 => 'く', 3 => 'ち', 4 => 'ん', } あ、4文字だと2マス足りない、しょうがないにゃあ・・・ DICE = { 1 => 'わ', 2 => 'く', 3 => 'ち', 4 => 'ん', 5 => 'お', # 追加 6 => 'こ', # 追加 } これで一安心(何が で”わくちん”を出すには4回ダイスを回さないといけないので def self.dice_throw 4.times { |_i| puts DICE[Random.rand(6) + 1] } end 超単純に4文字出力してくれるようになりました。 ここまでの結果 うん揃わない(白目 しかしここでは終わらない、やりたいことはワクチンワクチンしたかったので複数回回したいですよね。 って事で外部から何回回せるか渡せるようにします # 追加 Wkwktntn.injection(times: ARGV[0]&.to_i) def self.injection(times: 1) times.times { |time| dice_throw() } end ここまでの結果 うん、出来た(しかし揃わない 完成品 https://github.com/lunalice/wkwktntn 後書き コードを書いた時間3分 記事を書く時間が20分 皆さん時間は有意義に使いましょうね! わくちんわくちん出た人は教えてください?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6でjQueryを使おうとしたらハマった

Rails6.0.3にjQueryを入れようとしたら5日間ハマった話 by @tatsuhiko-nakayama様 こちらの記事で yarn add jquery config/webpack/environment.js const { environment } = require('@rails/webpacker') // 以下追記 const webpack = require('webpack') environment.plugins.prepend('Provide', new webpack.ProvidePlugin({ $: 'jquery/src/jquery', jQuery: 'jquery/src/jquery' }) ) // ここまで module.exports = environment config/webpack/environment.js const { environment } = require('@rails/webpacker') // 以下追記 const webpack = require('webpack') environment.plugins.prepend('Provide', new webpack.ProvidePlugin({ $: 'jquery/src/jquery', jQuery: 'jquery/src/jquery' }) ) // ここまで module.exports = environment config/javascript/packs/application.js //中略 require("@rails/ujs").start() require("turbolinks").start() require("@rails/activestorage").start() require("channels") // 追記 require('jquery') //中略 をやったのだが下のエラー発生 ERROR in ./app/javascript/packs/application.js Module build failed (from ./node_modules/babel-loader/lib/index.js): Error: Cannot find module './node_modules/@rails/webpacker/package/babel/preset.js' from '/myapp' webpackのインストールが失敗? いや、node_modulesとbabelって書いてあるからそこが不足しているのか… など色々試行錯誤したが、 結局アンインストールして入れ直しで解決 # webpacker:installで追加されたpackage.jsonから無効なbabelpresetを削除 yarn remove @rails/webpacker yarn remove webpack webpack-cli webpack-dev-server rm -fr node_modules rm -fr public/packs bundle exec rails webpacker:install Railsアプリの階層にある.browserlistrcを手動で削除する yarn add node-releases yarn add electron-to-chromium bundle exec rails webpacker:compile # おわり 備考 Rails6のwebpackerは壊れやすいようです。 npmも同じく壊れやすいらしいので色々インストールしてる間に、コンフリクトしたのかなと分析。 解決まで時間がかかり焦ってしまったが、明けない夜はないように明けないエラーもないのかなと。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む