20210511のRailsに関する記事は12件です。

User.allを使わない。selectへ。

本記事の目的: モデルから取り出す際に、不要なデータ量を抑える 結論 user_controller.rb(変更前 : def index @users = User.all.page(params[:page]) end def following @title = "フォロー" @user = User.find(params[:id]) @users = @user.following.page(params[:page]) render "show_follow" end : user_controller.rb(変更後 : def index @users = User.select(:id, :username). includes([:works, avatar_attachment: :blob]). page(params[:page]) end def following @title = "フォロー" @user = User.find(params[:id]) @users = @user.following.select(:id, :username). includes([:works, avatar_attachment: :blob]).page(params[:page]) render "show_follow" end : 本文 例の如くN+1問題の解消に取り掛かるべく、includesを用いて関連付けされているデータを同時に取り出す事で、クエリの発行を抑えていた。 そこでもう一つ。User.allの利用をやめることにした。理由としては、モデルから取り出す不要なデータ量を抑えるためである。解決方法としては、selectメソッドを用いることで、必要なデータだけを指定することとする。 具体例を以下に示します。 User.all => TRANSACTION (0.4ms) BEGIN User Load (0.8ms) SELECT `users`.* FROM `users` [#<User id: 1, username: "Test_User", email: "test@example.com", created_at: "2021-05-03 13:07:22.877662000 +0900", updated_at: "2021-05-03 13:07:58.184592000 +0900", uid: nil, provider: nil, description: "My name is Test_User", website: "http://example.com/">, #<User id: 2, username: "Mon Mothma", email: "test1@example.com", created_at: "2021-05-03 13:07:23.807304000 +0900", updated_at: "2021-05-03 13:07:58.296445000 +0900", uid: nil, provider: nil, description: "My name is Savage Opress", website: "http://example.com/">, : #<User id: 22, username: "Bail Organa", email: "test21@example.com", created_at: "2021-05-03 13:07:29.297810000 +0900", updated_at: "2021-05-03 13:07:29.297810000 +0900", uid: nil, provider: nil, description: "My name is Nute Gunray", website: "http://example.com/">] User.select(:username, :id) => User Load (1.3ms) SELECT `users`.`username`, `users`.`id` FROM `users` [#<User username: "Test_User", id: 1>, #<User username: "Mon Mothma", id: 2>, : #<User username: "Bail Organa", id: 22>] 以上のように結果は歴然であるが、必要なデータだけを取り出すことに成功した。ちなみにこれは、2行目にあるActiveRecordが発行するSQLの違いにより発生している。 User.all => User Load (0.8ms) SELECT `users`.* FROM `users` User.select(:username, :id) => User Load (1.3ms) SELECT `users`.`username`, `users`.`id` FROM `users` また、これは関連付けを行っているモデルにおいても同様の事が可能であった。 これもActiveRecordが発行するクエリに準じている事がわかる。 pry(main)> user = User.first User Load (1.9ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1 => #<User id: 1, username: "Test_User", email: "test@example.com", created_at: "2021-05-03 13:07:22.877662000 +0900", updated_at: "2021-05-03 13:07:58.184592000 +0900", uid: nil, provider: nil, description: "My name is Test_User", website: "http://example.com/"> # 変更前 pry(main)> user.following => User Load (0.9ms) SELECT `users`.* FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 [#<User id: 3, username: "Lyra Erso", email: "test2@example.com", created_at: "2021-05-03 13:07:24.080580000 +0900", updated_at: "2021-05-03 13:07:58.435753000 +0900", uid: nil, provider: nil, description: "My name is Jango Fett", website: "http://example.com/">, #<User id: 4, username: "Borvo the Hutt", email: "test3@example.com", created_at: "2021-05-03 13:07:24.351829000 +0900", updated_at: "2021-05-03 13:07:58.993427000 +0900", uid: nil, provider: nil, description: "My name is Darth Sidious", website: "http://example.com/">, : #<User id: 21, username: "Mon Mothma", email: "test20@example.com", created_at: "2021-05-03 13:07:29.023478000 +0900", updated_at: "2021-05-03 13:07:29.023478000 +0900", uid: nil, provider: nil, description: "My name is Jango Fett", website: "http://example.com/">] # 変更後 pry(main)> user.following.select(:id, :username) => User Load (1.7ms) SELECT `users`.`id`, `users`.`username` FROM `users` INNER JOIN `relationships` ON `users`.`id` = `relationships`.`followed_id` WHERE `relationships`.`follower_id` = 1 [#<User id: 3, username: "Lyra Erso">, #<User id: 4, username: "Borvo the Hutt">, : #<User id: 21, username: "Mon Mothma">] 以上です! 最後まで読んで頂きありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ユーザー管理機能をDeviseを使って実装する方法

1: Gemのインストール Gemfile # 最下部に追記 gem 'devise' ターミナル % bundle install # 再起動 control + C rails s 2: deviseの設定ファイルを作成 ターミナル % rails g devise:install 3: userモデルを生成 ターミナル % rails g devise user 4: マイグレーションの実行 #db/migrate/20XXXXXXXXX_devise_create_users.rb に記述 # マイグレーションを実行 % rails db:migrate # usersテーブルを確認 # ターミナルにて 再起動 control + C rails s # localhost:3000 で確認 5: deviseのビューを作成 ターミナル rails g devise:views # ログイン画面・サインアップ画面を編集 以上がdeviseを使ってユーザー管理機能を実装する方法でした!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails (apiモード)+ Docker + mysql 環境構築(メモ)

はじめに 学習したことのメモとして書いていきます。 ディレクトリ構造 api/  ├ Gemfile  ├ Gemfile.lock  ├ Dockerfile  ├ docker-compose.yml  ├ entrypoint.sh  Dockerfile dockercompose.yml Gemfile entrypoint.sh Dockerfile FROM ruby:2.7.3-buster RUN apt-get update #最新版のyarnをインストールできるように設定 RUN set -x && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list #nodeのバージョンを指定 RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \ apt-get install nodejs RUN apt-get install -y \ build-essential \ libpq-dev \ nodejs \ yarn RUN mkdir /api WORKDIR /api COPY Gemfile /api/ COPY Gemfile.lock /api/ RUN bundle install COPY entrypoint.sh /usr/bin/ #entrypoint.shの権限を付与 RUN chmod +x /usr/bin/entrypoint.sh #entrypoint.shを毎回実行 ENTRYPOINT ["entrypoint.sh"] #ポートを3000にする EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"] docker-compose.yml version: '3' volumes: db-data: api: build: context: . dockerfile: Dockerfile volumes: - './api:/api' ports: - '8000:3000' tty: true stdin_open: true depends_on: - db links: - db db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: root ports: - '3306:3306' volumes: db-data: でdockervolumeを作成してコンテナ内のデータベースにマウント。詳しくはこちらのブログ。 volumeの場所についてはこちら entrypoint.sh #!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@" Gemfile source 'https://rubygems.org' gem 'rails', '~>6' docker-compose run の実行 この状態でdocker-compose upしてもわたしコンテナはアクティブになりませんでした。 次にコマンドを実行します docker-compose run api rails new . --api --force --database=mysql --skip-bundle --skip-test --skip-bundle : Dockerfileでbundle install するのでbundleをスキップ --force : rails new で作られるファイルがすでに存在する場合上書き --skip-test : rspecを使うのでスキップ この後 docker-compose up を実行します。 database.ymlの編集 またdatabase.ymlのデフォルトの部分を以下のように編集する datbase.yml default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password host: db 最後にコンテナ内でrails db:create これでdocker-compose up を行った後、指定したポート(今回は8000)でURL(localhost:8000)を入力すればよく見るrails の画面が現れる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

herokuにデプロイした際にassetsに配置した画像が表示されない。

環境 Ruby 2.6.5 Rails 6.0.3.5 heroku エラー確認 ActionView::Template::Error (The asset "default_icon" is not present in the asset pipeline. //中略 <%= image_tag 'default_icon', id: 'preview-icon' %> herokuへのデプロイ後、アプリにアクセスし新規登録を行おうとした時に、上記のエラーが発生した。 image_tagでassets/imagesに配置している画像を指定しているのだが "default_icon"というアセットは存在しませんよと言われている。 開発環境では問題なく動作していたため本番環境由来のエラーだと判断し探索開始 参考記事 https://qiita.com/___xxx_/items/fa15f358beba2b9389da 公式ドキュメント 解決法 config/environments/production.rbファイルの書き換え # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false # <= trueに変換 本番環境ではフォールバックが無効化されているため画像のあるファイルを参照してくれていなかった様です。 RailsにおけるJSやCSSの取り回しの理解がまだまだ浅いので、この辺りもバックエンドの後に詰めたいですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rspec]未解決:Dockerを導入後、Rspecでエラーが発生

はじめに dockerとdocker-composeを導入したはいいが、テストでめちゃくちゃエラーがでたので備忘として記録する エラー内容 結合テストのみ例外なくエラーが発生 (一部抜粋) 47) Practices 投稿編集 投稿編集できないとき ログイン後、編集ページで、誤った情報が入力されているとエラー Failure/Error: url: ENV.fetch("SELENIUM_DRIVER_URL"), KeyError: key not found: "SELENIUM_DRIVER_URL" # ./spec/support/capybara.rb:7:in `fetch' # ./spec/support/capybara.rb:7:in `block (2 levels) in <main>' 試したこと おそらく自分が知らない知識として、「Docker上で結合テストを行うには環境構築が必要のなのだろう」と仮説を立てて、情報収集をおこなう。 こちらの記事に行き着くも,一向に変化はなし。 なお、ローカル上では間違いなくテストは成功していたことを考えると、間違いなくDockerを導入したことが影響していると考えられるので、ここらへんを疑って引き続き考えていきたい コード FROM ruby:2.6.5 RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs yarn WORKDIR /soccer_app COPY Gemfile /soccer_app/Gemfile COPY Gemfile.lock /soccer_app/Gemfile.lock RUN gem install bundler RUN bundle install COPY . /soccer_app RUN yarn install --check-files RUN bundle exec rails webpacker:compile docker-compose.yml version: "3" services: db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: "password" ports: - "4306:3306" selenium_chrome: image: selenium/standalone-chrome-debug logging: driver: none web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/soccer_app ports: - "3000:3000" depends_on: - db stdin_open: true tty: true environment: BASIC_AUTH_USER: ${BASIC_AUTH_USER:-default} BASIC_AUTH_PASSWORD: ${BASIC_AUTH_PASSWORD-default} Gemfile. source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.5' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.0' # Use mysql as the database for Active Record gem 'mysql2', '>= 0.4.4' # Use Puma as the app server gem 'puma', '~> 3.11' # Use SCSS for stylesheets gem 'sass-rails', '~> 5' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 4.0.0' gem 'factory_bot_rails' gem 'faker' gem 'rubocop', require: false end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' gem 'rubocop', require: false # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] gem 'devise' gem 'pry-rails' gem 'active_hash' gem 'carrierwave', '~> 1.3', '>= 1.3.1' gem 'mini_magick' gem 'image_processing', '~> 1.2' gem 'rails-i18n' gem 'kaminari' gem "gretel" gem 'simple_calendar', '~> 2.0' gem "aws-sdk-s3", require: false capybara.rb require 'capybara/rspec' RSpec.configure do |config| config.before(:each, type: :system) do driven_by :selenium, using: :headless_chrome, options: { browser: :remote, url: ENV.fetch("SELENIUM_DRIVER_URL"), desired_capabilities: :chrome } Capybara.server_host = 'web' Capybara.app_host='http://web' end end おわりに 今回はまじで解決しなさそうな匂いがぷんぷんしますが、諦めず、前向きに取り組んでいきます! はやくこの記事を解決済みに更新したいな〜
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Proc?lambda?違いは何?

はじめに 現場での開発にて、「Procや、lambdaってどうやって使うんだろう?」って思って、使い方が曖昧だったので、調べてみました! よく使う技術だと思うので、ぜひ習得しましょう! Procオブジェクトとは 処理をオブジェクトとして抽象化したもの。 これを使うことで、処理を使い回すことが可能です。 基本的な使い方 Proc.new { 処理 }で処理を作成して、.call()で実行出来ます。 sample = Proc.new do |name| puts "Hello, #{name}" # 最後に評価される式の値が戻り値となる end sample.call("Tanaka") #=> "Hello, Tanaka" lambdaとは? lambdaとはProcオブジェクトを作る方法の一つで、Procと比べて引数チェックとreturnの挙動に違いがあります。 sample = lambda { |name| puts "Hello, #{name}" } sample.call('Tanaka') #=> 'Hello, Tanaka' # 省略系 sample = ->(name) { puts "Hello, #{name}" } sample.call('Tanaka') #=> 'Hello, Tanaka' 引数チェックの相違 <Proc.newの場合> 引数が多い場合は、先頭から必要な数分だけ取って残りは無視する。 少ない場合は、足りない部分にnilを割り当てるます。 proc_sample = lambda do |a, b, c| p [a, b, c] end proc_sample.call(1, 2) #=> [1, 2, nil] <lambdaの場合> lambdaの場合は、引数の数が違うとArgumentErrorが発生します。 proc = lambda do |a, b, c| p [a, b, c] end proc.call(1, 2) => ArgumentError: wrong number of arguments (2 for 3) returnの挙動 <Proc.newの場合> return後は、メソッド自体を抜け出します。 def proc_method proc = Proc.new { return p "return proc"} proc.call p "proc method" end proc_method #=> "return proc" <lambdaの場合> lambdaの場合はreturnした後にメソッドに戻り、メソッドを最後まで実行します。 def lambda_method lambda1 = lambda { return p "return lambda"} lambda1.call p "lambda method" end lambda_method #=> "return lambda" #=> "lambda method" おわりに Procとlambdaの違いを理解して利用することで、現場での開発でも再利用可能で綺麗なコードを書くことが出来そうですね!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

知識0からProcオブジェクトについて調べてみた。

はじめに 現場での開発にて、「Procや、lambdaってどうやって使うんだろう?」って思って、使い方が曖昧だったので、調べてみました! よく使う技術だと思うので、ぜひ習得しましょう! Procオブジェクトとは 処理をオブジェクトとして抽象化したもの。 これを使うことで、処理を使い回すことが可能です。 基本的な使い方 Proc.new { 処理 }で処理を作成して、.call()で実行出来ます。 sample = Proc.new do |name| puts "Hello, #{name}" # 最後に評価される式の値が戻り値となる end sample.call("Tanaka") #=> "Hello, Tanaka" lambdaとは? lambdaとはProcオブジェクトを作る方法の一つで、Procと比べて引数チェックとreturnの挙動、breakの挙動に違いがあります。 sample = lambda { |name| puts "Hello, #{name}" } sample.call('Tanaka') #=> 'Hello, Tanaka' # 省略系 sample = ->(name) { puts "Hello, #{name}" } sample.call('Tanaka') #=> 'Hello, Tanaka' 引数チェックの相違 <Proc.newの場合> 引数が多い場合は、先頭から必要な数分だけ取って残りは無視する。 少ない場合は、足りない部分にnilを割り当てるます。 proc_sample = lambda do |a, b, c| p [a, b, c] end proc_sample.call(1, 2) #=> [1, 2, nil] <lambdaの場合> lambdaの場合は、引数の数が違うとArgumentErrorが発生します。 lambda_sample = lambda do |a, b, c| p [a, b, c] end lambda_sample.call(1, 2) => ArgumentError: wrong number of arguments (2 for 3) returnの挙動 <Proc.newの場合> return後は、メソッド自体を抜け出します。 def proc_method proc_sample = Proc.new { return p "return proc"} proc_sample.call p "proc method" end proc_method #=> "return proc" <lambdaの場合> lambdaの場合はreturnした後にメソッドに戻り、メソッドを最後まで実行します。 def lambda_method lambda_sample = lambda { return p "return lambda"} lambda_sample.call p "lambda method" end lambda_method #=> "return lambda" #=> "lambda method" breakの挙動 <Proc.newの場合> 例外が発生する。 def proc_method proc_sample = Proc.new do break 1 puts :unreachable end proc_sample.call p 'proc method' end proc_method #=> LocalJumpError: break from proc-closure <lambdaの場合> lambdaの場合はbreakした後にメソッドに戻り、メソッドを最後まで実行します。 def lambda_method lambda_sample = lambda do break 1 puts :unreachable end lambda_sample.call p "lambda method" end lambda_method #=> "lambda method" おわりに Procとlambdaの違いを理解して利用することで、現場での開発でも再利用可能で綺麗なコードを書くことが出来そうですね!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

db接続のエラー - PG::ConnectionBad: could not connect to server: No such file or directory -

1, 環境 macOS catalina 10.15.7 Ruby 2.6.5p114 Rails 6.0.3.7 2, はじめに エラーにハマって自身でしらべ、解消できたのですが今後も起きた時のためにも残しておきます。 また、同じエラーで困った人の助けになれば。 3, エラー内容 deviseの導入を行なっており、rails db:migrateを実行すると、 kanta@fukazawakantanoMacBook-Pro insta-app-daytra % rails db:migrate rails aborted! PG::ConnectionBad: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"? DBの接続に関してのエラーっぽいですね。 4, 試したこと エラー文をDeepLにて翻訳。 PG::ConnectionBad: サーバーに接続できませんでした。No such file or directory サーバーはローカルで動作していて、以下を受け付けています。 Unixドメインソケット「/tmp/.s.PGSQL.5432」で接続を受け付けていますか? なんとなくの意味は分かったが根本的な問題は分からず。 そこでエラー文の Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"? をググると、以下の記事がヒット →https://qiita.com/knxrvb/items/72d88fe5364561214e52 ターミナルでそこにあるコードを実行しDBを起動しようとすると postgres -D /usr/local/var/postgres 2021-05-11 15:22:39.356 JST [31540] FATAL: database files are incompatible with server 2021-05-11 15:22:39.356 JST [31540] DETAIL: The data directory was initialized by PostgreSQL version 12, which is not compatible with this version 13.2.   とログが表示。 翻訳すると、 データベースファイルがサーバーと互換性がない データディレクトリはPostgreSQLバージョン12で初期化されており、このバージョン13.2とは互換性がありません。 と、postgresのバージョンが古いみたい。 記事にもあるアップグレードさせるコードを実行。 brew postgresql-upgrade-database いろいろコードが走り、 ==> brew install postgresql@12 ==> Downloading https://ghcr.io/v2/homebrew/core/postgresql/12/manifests/12.6_2 ######################################################################## 100.0% ・    ・    ・ 一件落着かに思われたが、、、 Error: Upgrading postgresql data from 12 to 13 failed! ==> Removing empty postgresql initdb database... ==> Moving postgresql data back from /usr/local/var/postgres.old to /usr/local/var/postgres... Error: Failure while executing; `/usr/local/opt/postgresql/bin/pg_upgrade -r -b /usr/local/Cellar/postgresql@12/12.6_2/bin -B /usr/local/opt/postgresql/bin -d /usr/local/var/postgres.old -D /usr/local/var/postgres -j 4` exited with 1. アップグレードできず。。。 そのままエラー文の pgrading postgresql data from 12 to 13 failed! をググると →https://twin-t.com/postgressql%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC/ がヒット。 どうやらPostgresSQLを起動したままアップデートを行ったことがまずかったみたい。 記事に従って、PostgresSQLを停止させ、 brew services stop postgresql brew postgresql-upgrade-database . . . ==> Upgraded postgresql data from 12 to 13! ==> Your postgresql 12 data remains at /usr/local/var/postgres.old 無事アップグレード完了!! 試しにDBを起動させると、 brew services start postgresql ==> Successfully started `postgresql` (label: homebrew.mxcl.postgresql) 成功ですね!! rails db:migrateも実行できました!!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NameErrorが出た!

はじめに フリマアプリを作成中、NameErrorが出ました。 私の場合だいたい誤字の可能性があるので確認したのですが、誤字・脱字はなく別で原因がありました。 エラー箇所確認 商品出品機能の実装で商品を出品する際に必要なものをAcitiveHashを使って表示させようとしました。 app>models>shopping_date.rb class shopping_date < ActiveHash::Base self.data = [ { id: 1, name: '--'}, { id: 2, name: '1~2日で発送'}, { id: 3, name: '2~3日で発送'}, { id: 4, name: '4~7で発送'} ] include ActiveHash::Associations has_many :items end views>items>new.html.erb <div class="weight-bold-text"> 発送までの日数 <span class="indispensable">必須</span> </div> <%= f.collection_select(:shopping_date_id, shopping_date.all, :id, :name, {}, {class:"select-box", id:"item-scheduled-delivery"}) %> </div> </div> データをプルダウン形式で表示させたかったのでcollection_selectメソッドを使用しました。 結論:モデルの命名規則を忘れいていました モデルに命名規則がある事を忘れていました。 shopping_date.rbを確認するとモデルクラスが小文字でアンダースコア使用してました。 訂正をすると以下になります、 app>models>shopping_date.rb #訂正 class ShoppingDate < ActiveHash::Base self.data = [ { id: 1, name: '--'}, { id: 2, name: '1~2日で発送'}, { id: 3, name: '2~3日で発送'}, { id: 4, name: '4~7で発送'} ] include ActiveHash::Associations has_many :items end views>items>new.html.erb <div class="weight-bold-text"> 発送までの日数 <span class="indispensable">必須</span> </div> #訂正 <%= f.collection_select(:ShoppingDate_id, shopping_date.all, :id, :name, {}, {class:"select-box", id:"item-scheduled-delivery"}) %> </div> </div> 上手く反映されました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] chart.jsでRailsアプリにグラフを描画する [chart.js]

記事の概要  アプリで取り扱われるデータを可視化できればと思い、chart.jsを使ってRailsアプリにグラフを描いてみます。  1. chart.jsの導入手順  2. 記事投稿数の推移グラフを描いてみる chart.jsとは?  JavaScriptで実装されたグラフをRailsアプリに組込むことができるライブラリです。  公式  https://www.chartjs.org/docs/latest/ 1. chart.jsの導入手順  Gemfileに記述する。 Gemfile gem 'chart-js-rails', '~> 0.1.4'  そしてターミナルでbundle installを実行する。 % bundle install  package.jsonに以下の通り追記。 package.json { # 省略 "dependencies": { #省略 "chart.js": "^2.7.1" # ←ここに追記 } }  そしてターミナルでyarn installを実行。 % yarn install 2. 記事投稿数推移グラフを描いてみる  ここでは、とあるArticleモデルの投稿数推移について、Articlesコントローラーでデータを加工してarticles#indexにグラフ描画することをゴールとします。  横軸が日付、縦軸が投稿数です。なお、日時データを扱う"groupdate" gemは導入済みとして進めます。  まず、グラフ描画の基本構成は下記のようになります。公式ページのサンプル参照。 app/views/articles/index.html.erb <canvas id="myChart" width="200" height="100"> </canvas> <script> var ctx = document.getElementById("myChart").getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', # 'bar'でグラフタイプを縦棒グラフに指定  data: { labels: <%= @chartlabels %>, # 横軸にとるデータ(今回は投稿日付)を埋め込む datasets: [{ label: "投稿数", data: <%= @chartdatas %>, # 縦軸にとるデータ(今回は投稿数)を埋め込む backgroundColor: 'rgba(255, 80, 120, 1.0)', borderColor: 'rgba(255, 80, 120, 1.0)', fill: false }] }, }); </script>  グラフに渡すデータをarticles_controllerで用意しましょう。インスタンス変数を定義します。 app/controllers/articles_controller class ArticlesController < ApplicationController def index @articles = Article.all @article_by_day = @articles.group_by_day(:created_at).size # groupdateのgroup_by_dayメソッドで投稿日(created_at)に基づくグルーピングして個数計上。 # => {Wed, 05 May 2021=>23, Thu, 06 May 2021=>20, Fri, 07 May 2021=>3, Sat, 08 May 2021=>0, Sun, 09 May 2021=>12, Mon, 10 May 2021=>2} @chartlabels = @article_by_day.map(&:first).to_json.html_safe # 投稿日付の配列を格納。文字列を含んでいると正しく表示されないので.to_json.html_safeでjsonに変換。 # => "[\"2021-05-05\",\"2021-05-06\",\"2021-05-07\",\"2021-05-08\",\"2021-05-09\",\"2021-05-10\"]" @chartdatas = @article_by_day.map(&:second) # 日別投稿数の配列を格納。 # => [23, 20, 3, 0, 12, 2] end end  Railsアプリを起動し/indexへアクセスすると縦棒グラフが描画されている。  次に、累計投稿数を折れ線グラフにして、先ほどのグラフに重ねてみます。 app/views/articles/index.html.erb <canvas id="myChart" width="200" height="100"> </canvas> <script> var ctx = document.getElementById("myChart").getContext('2d'); var myChart = new Chart(ctx, { type: 'bar',   data: { labels: <%= @chartlabels %>, datasets: [{ label: "日別投稿数", data: <%= @chartdatas %>, backgroundColor: 'rgba(255, 80, 120, 1.0)', borderColor: 'rgba(255, 80, 120, 1.0)', fill: false },{ //ここから追記 label: "累積投稿数", data: <%= @cumulative %>, // 縦軸にとる累積投稿数データを埋め込む backgroundColor: 'rgba(255, 80, 120, 0.2)', borderColor: 'rgba(255, 80, 120, 1.0)', type: 'line', // 'line'でグラフタイプを折線グラフに指定 }] }, }); </script>  累積投稿数データを配列にして、インスタンス変数として用意します。 app/controllers/articles_controller class ArticlesController < ApplicationController def index @articles = Article.all @article_by_day = @articles.group_by_day(:created_at).size @chartlabels = @article_by_day.map(&:first).to_json.html_safe @chartdatas = @article_by_day.map(&:second) # ここから追記 @cumulative = [] sum=0 @chartdatas.each do |a| sum = sum + a @cumulative<<sum end end end  アプリを起動し/indexへアクセスすると、線グラフも表示されました。 まとめ  chart.jsを活用し、記事投稿数推移グラフを縦棒+折れ線グラフで表現できました。データベースから加工したデータをグラフで表現することができるので、アプリの管理者機能、可視化など幅広く活用できそうです。カスタマイズも柔軟にできそうなので、今後も記事で取扱いたいと思います。  Rubyでのデータ加工(もっと簡潔にできそう)とJavaScript記述の良いトレーニングにもなりました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Jp_prefectureとgeocoderでGoogle mapに表示させる方法

はじめに こんにちは、転職活動中のrails初心者のsatetoです。 まだまだ、わからないことだらけですが、日々頑張っています。 目標・環境 -環境- Mac Ruby '2.5.9' Rails '6.1.3' -目標- gem 'Jp_prefecture'を用いたテーブルから経度、緯度を保存し、 gem 'geocoder'でGoogle mapにピン立てする 導入 Google APIは取得、設定できている前提で進めます。 とりあえず、gemの追加 terminal gem 'Jp_prefecture' gem 'geocoder' gem 'gon' <=コントローラーで定義した変数をビューのJS内で使用出来るようにする。 terminal bundle install 実装 1.テーブル準備 gem 'Jp_prefecture'を使うには、住所を区分けして、保存する必要がある。 add_columns_to_users.rb class AddPostCodeToHotels < ActiveRecord::Migration[6.1] def change add_column :users, :postcode, :integer add_column :users, :prefecture_code, :integer add_column :users, :address_city, :string add_column :users, :address_street, :string add_column :users, :address_building, :string end end [:prefecture_code, :integer]ですが、 ー.prefecture_nameで都道府県名が表示できる 続いて、 gem 'geocoder'は住所から経度と緯度を取得し、表示するので add_columns_to_users.rb class AddColumnsToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :address, :string add_column :users, :latitude, :float add_column :users, :longitude, :float end end 後にも書きますが住所を分けた状態で、経度、緯度を取得する方法が思いつかなかったので addressカラムを追加 rails db:migrateを忘れずに 2.geocoder 設定 user.rb geocoded_by :prefecture_name + :address_city + :address_street after_validation :geocode この複数カラムを基準に緯度、経度を算出できると思ったのですが、 エラーが出たので、先程のaddressカラムに書き換えます。 2行目で住所変更時に緯度、経度も変更する。 user.rb geocoded_by :address after_validation :geocode APIの設定 config/initializers/geocoder.rb Geocoder.configure( lookup: :google, api_key: ENV['GOOGLE_MAP_API'] ) 3.コントローラー設定 users_controller.rb def show @user = User.find(params[:id]) gon.user = @user # 追記 end 問題はaddressカラムの保存ですが、かなりの時間考えましたが、私にはこの方法しか思いつきませんでした。 モデル.rbで書く方法や他の方法がありそうなので、わかる方がいれば教えて下さい。 今回この記事を書いたのは、ほとんどこのためです。 users_controller.rb def create @user = User.new(user_params) @user.address = @user.prefecture_name + @user.address_city + @user.address_street if @user.save flash[:notice] = "ユーザー情報を登録しました" redirect_to controller: :users, action: :show, id: @user.id else render :new end end private def user_params params.require(:user).permit(:name, :postcode, :prefecture_code, :address_city, :address_street, :address_building) end これで、住所入れた時に、addressカラムに完全な住所の情報が入ります。 ポイントは.new.saveメソッドを使っているところです。 コンソールで調べると、address、longitude、latitudeカラムにデータが入ってると思います。 4.ビューに表示 gem 'gon'を使うために追記 application.html.erb <html> <head> <title>Hoteresi</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= include_gon %> #追記 <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> Google mapの表示をします。 経度、緯度から探してピン立てします。 users/show.html <style>#map{ height: 450px;}</style> <script> let map; function initMap() { geocoder = new google.maps.Geocoder() map = new google.maps.Map(document.getElementById('map'), { center: { lat: gon.user.latitude, lng: gon.user.longitude }, zoom: 16, }); // ピン立て marker = new google.maps.Marker({ position: { lat: gon.user.latitude, lng: gon.user.longitude }, map: map }); } </script> <script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV["GOOGLE_MAP_API"] %>&callback=initMap" async defer></script> うまく行っていれば地図は表示されると思います。 参考文献 【Rails】Geocoding APIを用いて高精度で緯度経度を算出し、Google Mapに表示する方法 【Rails】jpostalとjp_prefectureを用いて住所自動入力の実装 【Rails】newとcreateの違い 最後に なにげに初投稿です、書き方に慣れていなくて時間かかりました笑 まだまだコードは初心者ですが頑張ります! 最後まで読んでいただきありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuインストール〜デプロイまでの基本手順

Herokuインストール〜デプロイするまでのコマンド備忘録です。 Herokuがインストールされていることの確認 $ heroku --version バージョンが表示されない場合は、以下のコマンドからHerokuをインストールする。 $ source <(curl -sL https://cdn.learnenough.com/heroku_install) Herokuにログインしてsshキーを追加 初回のみ。既に追加済みの場合はスキップする。 $ heroku login --interactive $ heroku keys:add Herokuサーバー上にアプリを作成 herokuにログインして、アプリのデプロイ場所を新規作成する。 $ heroku create コマンド実施後、アプリ専用のサブドメインが自動生成される。デプロイ前でも、出力されたURLにてブラウザでアクセス可能。 デプロイしたいアプリをherokuリポジトリにプッシュ $ heroku create実施時にリモートリポジトリにherokuが自動登録されるので、デプロイ対象のアプリをherokuにpushする。 $ git push heroku master データベースをマイグレーション アプリのデータベースを動作させる場合は、heroku run コマンドを実行してデータベースをマイグレーションする。 $ heroku run rails db:migrate ブラウザでURLにアクセス URLが不明な場合は以下のコマンドを実行してURLを確認できる。 $ heroku domain 【おまけ】herokuアプリの一覧表示 $ heroku apps Herokuでは、1アカウントにつき5つまでのアプリが作成可能(無料の場合)。オーバーする場合は$ heroku createに失敗する。 herokuアプリの削除 アプリが多くて削除したいといった場合には、以下のコマンドで削除可能。 $ heroku destory -app アプリ名 これでまた、デプロイ出来るね。(にっこり)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む