- 投稿日:2021-01-21T23:41:32+09:00
Railsのルーティングについて学び直そうと思う…①
- 投稿日:2021-01-21T23:05:12+09:00
【Rails Tutorial】第1章 ゼロからデプロイまで
はじめに
Railsチュートリアルをはじめるにあたり、演習の回答やエラーに対する解決方法、解決に至った経緯などを記録しています。
演習
1.3.2 rails server
1.3.2 - 1
デフォルトのRailsページに表示されているものと比べて、今の自分のコンピュータにあるRubyのバージョンはいくつになっていますか? コマンドラインでruby -vを実行することで簡単に確認できます。
デフォルトのRailsページRuby version: ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]自分のコンピュータにあるバージョンruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]1.3.2 - 2
同様にして、Railsのバージョンも調べてみましょう。調べたバージョンはリスト 1.2でインストールしたバージョンと一致しているでしょうか?
デフォルトのRailsページRails version: 6.0.3自分のコンピュータにあるバージョンRails 6.0.31.3.4 Hello, world!
1.3.4 - 1
リスト 1.9のhelloアクションを書き換え、「hello, world!」の代わりに「hola, mundo!」と表示されるようにしてみましょう。
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def hello render html: "hola, mundo!" end end1.3.4 - 2
Railsでは「非ASCII文字」もサポートされています。「¡Hola, mundo!」にはスペイン語特有の逆さ感嘆符「¡」が含まれています(図 1.23)17 。「¡」文字をMacで表示するには、Optionキーを押しながら1キーを押します。この文字をコピーして自分のエディタに貼り付ける方が早いかもしれません。
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def hello render html: "hola, mundo¡" end end1.3.4 - 3
リスト 1.9のhelloアクションを参考にして、2つ目のアクションgoodbyeを追加しましょう。このアクションは、「goodbye, world!」というテキストを表示します。リスト 1.11のルーティングを編集して、ルートルーティングの割り当て先をhelloアクションからgoodbyeアクションに変更します(図 1.24)。
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def hello render html: "hola, mundo¡" end def goodbye render html: "goodbye, world!" end endconfig/routes.rbRails.application.routes.draw do root 'application#goodbye' end1.5.3 Herokuにデプロイする(2)
1.5.3 - 1
1.3.4.1と同じ変更を行い、本番アプリでも「hola, mundo!」を表示できるようにしてください。
確認のみなので省略
1.5.3 - 2
1.3.4.1と同様、ルートへのルーティングを変更してgoodbyeアクションの結果が表示されるようにしてください。またデプロイ時には、Git pushのmasterをあえて省略し、git push herokuでデプロイできることを確認してみてください。
確認のみなので省略
1.5.4 Herokuコマンド
1.5.4 - 1
heroku helpコマンドを実行し、Herokuコマンドの一覧を表示してみてください。Herokuアプリのログを表示するコマンドはどれですか?
logs
1.5.4 - 2
上の演習で見つけたコマンドを使って、Herokuアプリの最近のログ(log)を調べてみましょう。直近に発生したイベントは何でしたか?(このログを調べるコマンドを覚えておくと、本番環境の不具合を見つけるときに役立ちます)
heroku logs
ちょっと小話
- 単語を選択するとき、ドラッグしなくても、単語をダブルクリックすると検索できる。
- Cloud9で行を下にコピーして、その行に移動したいときはcommand+option+down。 複数行を選択もできる。
GitHubにpushするときにエラーが出た
ターミナル$ git push -u origin master上のコードを実行した結果…
ターミナルunable to access 'https://github/moutoon/hello_app.git/': Could not resolve host: git hub [ 翻訳 ] 'https://github/moutoon/hello_app.git/' にアクセスできません。ホストを解決できませんでした: git hub原因はプロキシサーバを経由してGitHubへ接続しているらしい。
色々調べてみましたが解決できず、httpsからsshに変更することにしました。
- 新しいSSH Keyを作成
- GitHubアカウントにSSH Keyを登録
- Gitのリモートリポジトリをhttpsに設定しているのでsshに変更
無事解決!
参考にしたサイト・記事
おわりに
はじめて学習の記録をQiitaで書いてみましたが、めちゃくちゃ難しいなぁと実感しました。
- どうしたら読みやすいか
- 何を伝えたいのか
- 効果的な見出しやマークダウン記法は何か
- お硬い文章になるのでもう少しユーモアを入れたい
いろいろ考えながら文章を書くと大変ですが、完璧でなくても書ききった自分を褒めてあげたいと思います。
- 投稿日:2021-01-21T22:16:32+09:00
#Rails redirect_toではhttpリクエストをgetからdeleteに変更できない!?
Rails redirect_toではhttpリクエストをgetからdeleteに変更できない!?
rails 5.2.2
を使ってます。今回はユーザーの退会ボタンを押したら退会処理がなされてかつ、ログアウトされ、ログイン画面に飛ばすような設計にしてそれを実装しようとしていたのですが、そこで問題が発生しました!!
それは退会処理後のログアウトを呼び出そうとして
redirect_to user_sessions_path
を実行したところ、「httpリクエストがgetですよ」とのことでdeleteに修正しようとしたが
残念
redirect_to user_sessions_path, method: :delete
ではできなかった
これ以上解決方法が浮かばなかったのでいろいろ調べたところ
deleteになってしまった場合はstatusコードを編集することでgetにできるらしいが
getからdeleteは無理なようだ・・・
postは指定できないことは知っていたがまだredirect_toに弊害があったとは・・・皆さんもきおつけてくださいね
僕はこれに2時間近く囚われてしまい悔しいです笑笑
- 投稿日:2021-01-21T22:03:39+09:00
Docker ComposeでApache+Rails環境を構築
最終的なフォルダ構成
最終的なフォルダ構成myapp/ |--docker-compose.yml |--apache/ |--html/ |--rails/ |--app/ |--bin/ |--config/ |--db/ |--lib/ |--log/ |--public/ |--storage/ |--test/ |--tmp/ |--vendor/ |--config.ru |--Dockerfile |--entrypoint.sh |--Gemfile |--Gemfile.lock |--Rakefile |--README.md |--.env |--.gitignore |--.git.git
Gitの初期化を行う
bashgit init.gitignore
- Gitの管理下に置きたくないファイルやディレクトリを管理するためのファイル
.gitigrore/.env.env
- 環境変数を管理するために使われるファイル
.env# commons WORKDIR=app CONTAINER_PORT=3000 RAILS_PORT=3000 APACHE_PORT=8080 # db # POSTGRES_PASSWORD=passworddocker-compose.yml
まずプロジェクトフォルダを作成し、そこにrailisフォルダ、apacheフォルダとdockercompose.ymlファイルを作成する。
docker-compose.ymlversion: '3.8' services: apache: image: httpd:alpine container_name: apache volumes: - ./apache/html:/usr/local/apache2/htdocs # httpdイメージでは80番ポートを公開している ports: - "$APACHE_PORT:80" depends_on: - rails # railイメージを構築、railsコンテナを構築、起動 rails: # railsフォルダの中にあるDockerfileをビルド build: context: ./rails # Dockerイメージをビルドする際にDockerfileに渡す値を指定 args: WORKDIR: $WORKDIR container_name: rails environment: # rack-corsで使用する ACCESS_CONTROL_ALLOW_ORIGIN: "localhost:$APACHE_PORT" # サーバの起動フラッグを削除(起動されていると勘違いしてしまわないように) # ポートを$CONTAINER_PORTとしてサーバ起動(Dockerfile内でも起動しているが) command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p $CONTAINER_PORT -b '0.0.0.0'" # コンテナ中のappフォルダをローカルのappフォルダに結びつける(コンテナを起動する際にホストマシン上のデータがコンテナにマウントされる) volumes: - ./rails:/$WORKDIR # コンテナのポートとホストのポートを対応付ける ports: - "$RAILS_PORT:$CONTAINER_PORT" # attachに必要,ターミナルの入出力がコンテナのbashとつながる?,attachしないとブラウザは一生読み込み中に stdin_open: true # これがないとattachしてもすぐ切れてしまう? tty: trueCORSの設定
CORSとは、異なるオリジン感の通信を許可する仕組み
- Gemのインストール
- railsディレクトリのGemfileを開く
- 26行目付近の
gem 'rack-cors'
のコメントを外す- Dockerイメージを再ビルド
設定ファイルの編集
- api/config/initializers直下にあるcors.rbが設定ファイル
下記のように編集
cors.rb# Be sure to restart your server when you modify this file. # Avoid CORS issues when API is called from the frontend app. # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. # Read more: https://github.com/cyu/rack-cors Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do # docker-compose.ymlで指定した値かその値がNullの場合は、空文字を入れる(エラーにならないように) origins ENV["ACCESS_CONTROL_ALLOW_ORIGIN"] || "" # 許可したいリソースファイル resource '*', headers: :any, # getのみ許可 methods: [:get] end endDockerfile
railsイメージはDockerfileから作成するためDockerfileとentrypoint.shをrailsフォルダの下に作成する。
現在のフォルダ構成myapp/ |--docker-compose.yml |--apache/ |--rails/ |--Dockerfile |--entrypoint.shDockerfileFROM ruby:2.7.2 RUN apt update -qq && \ apt install -y build-essential \ libpq-dev # Dockerfile内で使用する変数名を指定 ARG WORKDIR ENV APP_ROOT /$WORKDIR RUN mkdir $APP_ROOT WORKDIR $APP_ROOT # このファイル(Dockerfile)と同じ階層にあるGemfile等をコンテナにコピー COPY ./Gemfile $APP_ROOT/Gemfile COPY ./Gemfile.lock $APP_ROOT/Gemfile.lock # コンテナのGemfileを参考にGemをインストール RUN bundle install # このファイルが含まれているディレクトリをコンテナのルートディレクトリにコピー COPY . $APP_ROOT COPY ./entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] CMD ["rails", "server", "-b", "0.0.0.0"]entrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /app/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"GemfileとGemfile.lock
現在のフォルダ構成myapp/ |--docker-compose.yml |--apache/ |--rails/ |--Dockerfile |--entrypoint.sh |--Gemfile |--Gemfile.lockGemfilesource 'https://rubygems.org' gem 'rails', '6.0.0'GemfileはRubyのライブラリをまとめたもので、Dockerfile内の
bundle install
ではこのファイルを元にgemたちをインストールしている。
Gemfile.lockはGemfileをもとに実際にインストールされたgemの一覧とバージョンが記載されたファイルで、ここでは空のファイルを作成しておく。イメージの構築、コンテナの作成・起動
ここまででとりあえず必要なファイルが揃ったので、イメージの構築等を行っていく。
rails new —api
rails new
はrailsアプリケーションの雛形を作成してくれるコマンドで、railsサーバを立ち上げるのに必要なgem等を作成してくれる。今回railsはAPIサーバとして用いるためAPIモードでアプリを作成するように--api
をオプションとして付けている。bashdocker-compose run rails rails new . --api --force --skip-bundle
docker-compose run
は引数で指定したサービスについて、イメージの構築から、コンテナの作成・起動までを行ってくれるコマンドで、それプラスサービス名の後にコマンドを打つとコンテナ内で実行してくれる。
ここではサービスにDockerfileで指定したrails:を指定しており、プラスアルファのコマンドとしてrails new .
を行っている。
--force
は既存のGemfileを上書きするためのオプションである。
後で、イメージを構築する際にbundle install
は行われるので、ここでは--skip-bundle
としている。イメージの構築
bashdocker-compose buildこのとき、Dockerfileよりrailsのイメージが作成される。
コンテナの作成・起動
bashdocker-compose uphttpdのイメージはこのときに、Docker Hubからローカルに持ってきている。
localhost:8080で
apache/html
にアクセスできる。localhost:3000でrailsサーバにアクセスできる。補足
docker-compose build
でbundle install
は行われるが、volumeとは紐付かないらしく、コンテナを起動する際にエラーが出る恐れがある。そのときは、volumeと紐づけられるrun
コマンドを実行する。$ docker-compose run rails bundle installまたは、
rails new
で--skip-bundle
を付けなければ問題ない。Docker Compose + Railsでイメージ内でbundle installしているはずなのにgemが無いとエラーがでる。 - Qiita
参考
DockerインストールからRails + Docker + MySQLで環境構築までの手順
【Mac編】DockerでRuby on Railsの開発環境を作ってみよう
Docker ComposeでNode.jsの環境構築 - Qiita
Rails6・Nuxt.js・PostgreSQLを動かすdocker-compose.ymlファイルを作成する - 独学プログラマ
- 投稿日:2021-01-21T21:38:46+09:00
【Rails】【Controllerから外部APIを叩く】 OpenWeatherMap APIで天気情報を取得
はじめに
外部APIを叩くという経験が初めてだったので、どんな大変な作業が待っているのだろうと心構えをしていたのですが、驚いたことに
実は難易度が低くて、高機能が実装できるハイコスパな方法
でした。
今回実装した機能の概要は以下の通りです。メモ程度ですが参考程度に載せておきます。前提
- deviseでユーザーに関する機能作成済み
- food_record(料理記録)モデルを作成済み
- new, createなどの基本的な機能は既に実装済み
環境構築
- Ruby2.7
- Ruby on Rails6
API_KEYの取得
OpenWeatherMapで会員登録して、API_KEYを取得します。こちらは、多くの記事が出回っているので、割愛させて頂きます。
https://qiita.com/matsubishi5/items/fcd77eacb0ed111299e2
↑私はこちらを参照しました。
http://api.openweathermap.org/data/2.5/weather?q=Tokyo&appid=
末尾に取得したAPI_KEYを貼り付けて、ブラウザで実行してみてください。東京の今の天気が返ってくるはずです。これだけで、APIってこんなものかと実感できますし、疎通確認の意味でもやっておいた方が無難です。
ちなみに、会員登録からAPI_KEYが使えるようになるまで数時間程度かかります。(いくぞうは、3時間くらいでした)必要なライブラリをインストール & API_KEYを格納
Gemfile.#API_KEYを環境変数として管理する(Keyを外部流出させないための措置) gem 'dotenv-rails' #アプリケーション内でHTTPリクエストを投げたい場合に使うクラス gem 'httpclient'Gemfile記載後、bundle installします。
..env.
OPEN_WEATHER_MAP_API = 'API_KEY貼り付け'
URI = 'https://api.openweathermap.org/data/2.5/weather'
.envには、前もって取得したAPI_KEYをコピペします。
.gitignore./.envここで絶対に忘れずに.gitignoreを作ってください。.envをgithubにpushした場合、全世界にAPI_KEYを晒すことになってしまいます。(私は1回やらかしました、、、)
APIを叩く処理
controllerでAPIを叩きます。
-Api::OpenWeatherMap::Request
という処理がありますが、こちらで、下記モジュール(request.rb)を呼び出しています。
- コードがブサイクでごめんなさい!!!!でもちゃんと動きます。food_records_controller.rbdef create #料理記録 @food_record = current_user.food_records.build(food_record_params) @food_record.food_date = Time.zone.today #天気API #リクエストを出す open_weather = Api::OpenWeatherMap::Request.new(current_user.location_id) #戻り値を受け取る response = open_weather.request if @food_record.valid? #APIが正常に動作した場合 if response['cod'] == 200 params_weather = Api::OpenWeatherMap::Request.attributes_for(response) @food_record.update(params_weather) flash[:notice] = "登録に成功しました" else #APIが正常に動作しない場合も料理情報は記録する flash[:notice] = "天気情報の取得に失敗しましたが、登録に成功しました" end redirect_to root_url else render 'new' end end
- 処理本体は、モジュールに書きました。
- 今回、取得する天気の地域
としてlocation_idを使用していますが、'id: location_id'をq: 'Tokyo'
というように変えても上手くいきます。lib/api/open_weather_map/request.rbmodule Api module OpenWeatherMap class Request attr_accessor :query def initialize(location_id) @query = { id: location_id, units: 'metric', appid: 'OPEN_WEATHER_MAP_API'] } end def request client = HTTPClient.new request = client.get(ENV['URI'], query) JSON.parse(request.body) end # 取得したjsonをparamsに変換 def self.attributes_for(attrs) { weather_main: attrs['weather'][0]['main'], weather_description: attrs['weather'][0]['description'], weather_icon: attrs['weather'][0]['icon'], weather_id: attrs['weather'][0]['id'], temp: attrs['main']['temp'], temp_max: attrs['main']['temp_max'], temp_min: attrs['main']['temp_min'], humidity: attrs['main']['humidity'], pressure: attrs['main']['pressure'] } end end end end
lib以下はデフォルトではtask以外読み込まれないので、config/application.rbに、以下の設定が必要ですconfig/application.rbconfig.paths.add 'lib', eager_load: true完成
<%= image_tag "http://openweathermap.org/img/wn/#{@food_record.weather_icon.chop}d@2x.png" %>
アイコンはこのように表示させています。chop処理をしているのは、夜に天気を取得すると、太陽が黒色になってしまうからです。
{@food_record.weather_icon.chop}d
このようにchopで末尾のnを削って、d「昼間(おそらくdaytime)」を付け足しています。補足
- 今回はlocation_idを使用しました。私は、下記のCSVを読み込ませて、cityテーブルに初期データとして投入して使用しています。
- 都市名, location_id, 緯度, 経度 の順になっています。
- 説明は割愛しますが、下記のようにすれば簡単に実装できます。
db/csv/cities.csv札幌,2128295,141.346939,43.064171 青森,2130658,140.740005,40.82444 盛岡,2111834,141.152496,39.703609 仙台,2111149,140.871933,38.26889 秋田,2113126,140.116669,39.716671 山形,2110556,140.363327,38.240559 福島,2112923,140.467773,37.75 水戸,2111901,140.446671,36.341389 宇都宮,1849053,139.883606,36.56583 前橋,1857843,139.060837,36.391109 さいたま,1853226,35.857208 千葉,2113015,140.123337,35.604721 東京,1850147,139.691711,35.689499 横浜,1848354,139.642502,35.447781 新潟,1855431,139.023605,37.902222 富山,1849876,137.211395,36.695278 金沢,1860243,136.625565,36.59444 福井,1863983,136.225174,35.850101 山梨,1848649,138.608002,35.61602 長野,1856210,138.040771,36.13464 岐阜,1863640,137.053986,35.78091 静岡,1851715,138.325424,35.025219 名古屋,1856057,136.906403,35.181469 津,1849796,136.508606,34.730282 大津,1853574,135.868332,35.00444 京都,1857910,135.753845,35.021069 大阪,1853909,135.502182,34.693741 神戸,1859171,135.182999,34.691299 奈良,1855612,135.804855,34.685051 和歌山,1926004,135.167496,34.226109 鳥取,1849890,133.850815,35.367859 松江,1857550,133.050568,35.472221 岡山,1854383,133.934998,34.661671 広島,1862415,132.459366,34.396271 山口,1848689,131.47139,34.185829 徳島,1850158,134.559433,34.06583 高松,1851100,134.043335,34.340279 松山,1926099,132.765747,33.839161 高知,1859146,133.531113,33.559719 福岡,1863967,130.41806,33.606392 佐賀,1853303,130.298798,33.249321 長崎,1856177,129.873611,32.74472 熊本,1858421,130.741669,32.789719 大分,1854487,131.612503,33.23806 宮崎,1856717,131.423889,31.91111 鹿児島,1860827,130.558136,31.560181 那覇,1856035,127.681107,26.2125db/seeds.rbrequire "csv" CSV.foreach('db/csv/cities.csv') do |row| City.create( name: row[0], location_id: row[1], lon: row[2], lat: row[3] ) end
上記ファイルを作って、cityテーブルも作成済みならば、下記コマンドを実行します。rails db:seed最後に
少しでも参考になればLGMTよろしくお願いします。
また、説明不十分な点や、説明が間違っている箇所が御座いましたら、コメントいただけると幸いです。Twitterもやっているので、よかったらフォローお願いします!!
https://twitter.com/engineer_ikuzou
- 投稿日:2021-01-21T19:22:44+09:00
Rubocopの導入
はじめに
オリアプ制作でRubocopを導入したので、載せておこうと思います。
( Rubocop:静的コード解析ツールのことで、余分なスペースやインシデントが揃っていないなどを指摘・修正してくれるGem )
オリアプのコードは誰かに直接見てもらう事はないので、導入する必要はないかなと思ったのですが、今後使用するかもしれないと思い、導入しました。1.Gemの導入・ファイル作成
1.Gemfileにrubocopを記述し、bundle installする。
コードはgroup :development do ~ end 内に記述する。Gemfilegroup development do #中略 gem 'rubocop', require: false end2.rubocopの設定コードを記述するファイル ( .rubocop.yml ) をプロジェクト直下に作成する。
2.Rubocopの設定
作成した .rubocop.yml に設定用のコードを記述していく。
以下のコードはあくまで一例であり、調べればまだある。.rubocop.ymlAllCops: Exclude: # 除外するディレクトリ - "vendor/**/*" - "db/**/*" - "config/**/*" - "bin/*" - "node_modules/**/*" - "Gemfile" # メソッドの行数が多すぎないかをチェック Metrics/MethodLength: Max: 30 # クラスの行数をチェック(無効) Metrics/ClassLength: Enabled: false # ブロック内の行数をチェックする Metrics/BlockLength: Exclude: # チェックの対象から除外 - "spec/**/*" # 下記項目を計算して基準値を超えると警告する(下記頭文字をとって'Abc') # ・Assignment: 変数への代入 ・Branch: メソッド呼び出し ・Condition: 条件文 Metrics/AbcSize: Max: 50 # メソッドの中身が複雑になっていないか、計算して基準値を超えると警告する Metrics/PerceivedComplexity: Max: 8 # 1行あたりの文字数をチェックする Layout/LineLength: Max: 130 Exclude: # チェックの対象から除外 - "Rakefile" - "spec/rails_helper.rb" - "spec/spec_helper.rb" # 循環的複雑度が高すぎないかをチェック(ifやforなどを1メソッド内で使いすぎている) Metrics/CyclomaticComplexity: Max: 10 # ネストが深すぎないかをチェック(if文のネストもチェック) Metrics/BlockNesting: Max: 5 # メソッドパラメータ名の最小文字数を設定 Naming/MethodParameterName: MinNameLength: 1 # 日本語でのコメントを許可 Style/AsciiComments: Enabled: false # クラス内にクラスが定義されていないかチェック(無効) Style/ClassAndModuleChildren: Enabled: false # 文字列に値が代入されて変わっていないかチェック(無効) Style/FrozenStringLiteralComment: Enabled: false # クラスやモジュール定義前に、それらの説明書きがあるかをチェック(無効) Style/Documentation: Enabled: false # %i()構文を使用していないシンボルで構成される配列リテラルをチェック(無効) Style/SymbolArray: Enabled: false # 空メソッドの場合に、1行のスタイルにしない Style/EmptyMethod: EnforcedStyle: expanded3.Rubocopの実行
以下のコマンドを実行することでRubocopが余分な箇所などを指摘してくれる。
ターミナル% bundle exec rubocopまた、以下のコマンドを実行することでRubocopがさきほどの指摘を自動で修正してくれる。
ターミナル% bundle exec rubocop -a以上、導入完了!!!
最後に
rubocopの設定用のコードを覚えるのは無理なので、もし使う機会があれば、この投稿を参考に導入していきたいと思います。
参考
以下の投稿を参考にさせて頂きました。ありがとうございました。
https://qiita.com/tomohiii/items/1a17018b5a48b8284a8b
- 投稿日:2021-01-21T18:56:00+09:00
[Rails] gem jsonを使って、APIを叩く。
今回は、weather APIにしました。(https://openweathermap.org/)
APIの取得方法
gem jsondef home require 'net/http' require 'json' @url = 'http://api.openweathermap.org/data/2.5/weather?q=berlin,de&appid=ここにapikey。' @uri = URI(@url) @response = Net::HTTP.get(@uri) @output = JSON.parse(@response) endoutput
<%= @output %>です。
- 投稿日:2021-01-21T18:39:38+09:00
RailsでPostgreSQLを使うぞ!「FATAL: role "postgres" does not existの解消」にむけて
はじめに
Railsチュートリアなんとか一通り終え(理解度としては3割程度なので終えたと言えるかどうかはおいといて...)、
自身のローカル環境にてRuby, Railsの環境を構築する際に発生した問題に関して、自身のメモのため、初学者の方で同様の問題が発生した方向けに投稿します!開発環境
- macOS Catalina 10.15.7
- MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)
- プロセッサ 1.4 GHz クアッドコアIntel Core i5
メモリ 8GB
Ruby 2.5.7
Rails 5.2.3
PostgreSQL 13.1
導入までの一連の流れに関して
一連の環境構築までの流れに関しては下記記事が大変参考になると思いますので、ぜひ見てください。
今回はPostgreSQLの導入部にフォーカスして記事を作りたいと思います!【完全版】MacでRails環境構築する手順の全て
https://qiita.com/kodai_0122/items/56168eaec28eb7b1b93bエラー FATAL: role "postgres" does not exist の発生
ここからが本題です!
一通り上記記事を参考に環境構築を終え、railsを起動しようとしたところ、$ rails s下記のようなエラーが発生し、railsをが起動できない状況に...
ん?そもそもロールってなに?
詳しくは下記が参考になると思いますが、PostgreSQL 11.5文書
https://www.postgresql.jp/document/11/html/role-attributes.html「PostgreSQLは、ロールという概念を使用してデータベースへの接続承認を管理する」らしい。
つまり、role postgres does not existというのは、ロール(データベースへアクセスする権限みたいなもの?)として、postgreがないよっていことで解釈しました。そこで実際に下記コマンドを使用して、データベースのロール状態を確認すると...
$ psql postgrespsql (11.4) Type "help" for help. postgres=# \du # 現在のロール確認(ちなみにバッククオート\は「option+¥」キーですよ)Role name | Attributes | Member of ---------------+------------------------------------------------------------+----------- araishuntarou | Superuser, Create role, Create DB, Replication, Bypass RLS | {} | | {}やはりRole nameにpostgresがない!!
では、ここのroleにpostgresを追加すれば全てが解決できるぞと思い、
コマンド入力! そしてすかさず確認!$ createuser postgres$ psql postgrespsql (11.4) Type "help" for help. postgres=# \du # 現在のロール確認(ちなみにバッククオート\は「option+¥」キーですよ)Role name | Attributes | Member of ---------------+------------------------------------------------------------+----------- araishuntarou | Superuser, Create role, Create DB, Replication, Bypass RLS | {} postgres | | {}やったー!roleにpostgresが追加できてる。うれしー。これで解決と思いました...。
第二の関門 PG::InsufficientPrivilege: ERROR: permission denied to create database
やっとの思いで、railの起動まで辿り着きましたが、
$ rails s
なんとまたエラーが発生!!心折れます....。
PG::InsufficientPrivilege: ERROR: permission denied to create database
う~ん、データベースを作る権限がないということかな?言われてみれば確かに、postgresのAttributesに何の記述もされていないぞ。
Role name | Attributes | Member of ---------------+------------------------------------------------------------+----------- araishuntarou | Superuser, Create role, Create DB, Replication, Bypass RLS | {} postgres | | {}そこで、postgres にsuperuserの権限を与えようと下記コマンドを実施!
superuserは「ログイン以外に何でもできる権限をロールに与える」ため、危険な場合もあるとのこと。
(ここら辺はあとで勉強しよう... 本来は目的に応じた権限のみを与えた方がいいのかも)$ psql postgrespsql (11.4) Type "help" for help. postgres=# DROP ROLE postgres ; # 一度postgresを削除(役割だけを追加する方法が不明..) postgres=# CREATE ROLE postgres SUPERUSER ; # superuserの権限を持ったpostgresを作成! postgres=# \du # 現在のロール確認Role name | Attributes | Member of ---------------+------------------------------------------------------------+--------- araishuntarou | Superuser, Create role, Create DB, Replication, Bypass RLS | {} postgres | Superuser | {}やっとここまできたか...
最後の関門 ActiveRecord::PendingMigrationError
datebaseをmigrateしてないですよという意味だと捉え、
$ rails db:create #データベース自体(テーブルを保管しておく全体のシステム)を作るからの
$ rails db:migrate #データベースの中にテーブルを作ったり、カラムを変更したりするときに実行するを実行!!
最後に
$ rails s出来たー!!!!
最後に
稚拙な文章にもかかわらず最後までお読みいただきまして誠にありがとうございました。
私も完全には理解できていないところが多く、これかわも勉強しなければなりませんが、
少同じ問題で困っている方々の助けに慣れれば幸いです!
- 投稿日:2021-01-21T17:49:55+09:00
複数の画像投稿/表示をさせたいとき(refile使用)
Railで作成するアプリ内で写真投稿や表示をさせたい時にrefileを使う方へ。
下記の手順で本来であれば1枚のみしか投稿・表示できないところ、
複数の写真を投稿・表示できるようになります。1.rifleの準備
Gemfileに下記を記入後、「bundle install」ください。
gem "refile", require: "refile/rails", github: 'manfe/refile' gem "refile-mini_magick"2.テーブルの作成
複数枚の写真を投稿・表示させる場合、
「写真を表示させるモデル」と「写真を保存しておくテーブル」が必要になります。db/schema.rbcreate_table "shops", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "shop_images", force: :cascade do |t| t.string "shop_image_id" t.integer "shop_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end3.モデルの設定
先ほど作成したテーブルのモデルにて、それぞれの関係を1:多の関係で紐付ける必要があります。
(ここでは例として、「shopモデル」に紐づく「shop_imageモデル」で解説しています。
「shop」はあくまで例ですので、ご自身の作成されているモデル名に合わせて修正ください)shop.rbbelongs_to :shop #1:多の紐付け attachment :shop_image #shop_image(_id)をshopのviewにて表示させるための設定shop_image.rbhas_many :shop_images, dependent: :destroy #1:多の紐付け accepts_attachments_for :shop_images, attachment: :shop_image #shop_image(_id)をshopのviewにて表示させるための設定4.コントローラーの設定
shopコントローラーのnewアクション(投稿)、showアクション(一覧表示)、
ストロングパラメータをそれぞれ記述していきましょう。(※shop_imageコントローラーは作成しません)shops_cotroller.rbdef new @shop = Shop.new #空データを作成 @shop.shop_images.new #写真の空データを作成 end def show Shop.find(params[:id) end private def shop_params params.require(:shop).permit(shop_images_shop_images: []) #shop_images_shop_images → shop_imagesテーブルの複数のshop_imageを指定 #: [] → 指定した複数のshop_imageを配列に入れます(配列に入れて管理するため) end5.ビューの記述
投稿ページ(new.html)と投稿ページ(show.html)を記述していきましょう。
app/views/shops/new.html.erb<%= form_with model: @shop, local:true do |f| %> <table> <tbody> <td> <%= f.attachment_field :shop_images_shop_images, multiple: true %> </td> </tbody> </table> <% end %>↑「multiple:true」にすることで複数投稿が可能になります。
app/views/shops/show.html.erb<table> <td> <% if @shop.shop_images.present? %> <% @shop.shop_images.each do |shop_image| %> <%= attachment_image_tag shop_image, :shop_image, :fill, 200, 200 %> <% end %> <% else %> <%= image_tag "no_image.jpg", size: "200x200" %> <% end %> </td> </table>↑「no_image.jpg」は別途用意していただく必要があります。
「app/assets/images」に用意頂いたデータを入れてください。
no_image_jpg (urlを開いていただいた後、右クリックでダンロードください)6.ブラウザ上にて複数の画像を選択する方法
複数の画像をアップロードする場合は、「ファイル選択」をクリック後、
Shift + クリック, または Ctrl + クリックで画像を選択ください。参考に記事
- 投稿日:2021-01-21T16:56:54+09:00
Formオブジェクトを用いて作成したデータを、編集・更新する方法
要点
- 初心者がアプリを作るときの参考に
- formオブジェクトを用いた編集・更新機能は複雑なので詳しく知りたいorおさらいしたい
- 下記のエラーを解消する方法
param is missing or the value is empty: 'Formオブジェクト名'はじめに
メルカリのようなフリマアプリを作成中で、Formオブジェクトを用いて商品にタグ付けして編集・更新(edit・update)する機能を実装まで行いました
各モデルとコントローラーは以下のようになります
- Item/商品
- Tag/タグ
- TagItemRelation/商品とタグの中間テーブル
- TagsItem/ ItemとTagを同時に保存するためのFormオブジェクト
/app/model/item.rbclass Item < ApplicationRecord has_many :tag_item_relations, foreign_key: :item_id, dependent: :destroy has_many :tags, through: :tag_item_relations end/app/model/tag.rbclass Tag < ApplicationRecord has_many :tag_item_relations has_many :items, through: :tag_item_relations validates :tag_name, uniqueness: true end/app/model/tag_item_relation.rbclass TagItemRelation < ApplicationRecord belongs_to :item belongs_to :tag end/app/form/tags_item.rbclass TagsItem include ActiveModel::Model attr_accessor :item_name, :tag_name with_options presence: true do validates :item_name end def save item = Item.create(item_name: item_name) tag = Tag.where(tag_name: tag_name).first_or_initialize tag.save TagItemRelation.create(item_id: item.id, tag_id: tag.id) end endコントローラー
/app/controller/items_controller.rbclass ItemsController < ApplicationController def index @items = Item.all.order('created_at ASC') end def edit @item = current_user.items.find(params[:id]) @tegs_item = TagsItem.new(item: @item) end def update @item = current_user.items.find(params[:id]) @tags_item = TagsItem.new(update_items_params, item: @item) if @tags_item.valid? @tags_item.save redirect_to root_path else render :edit end end private def update_items_params params.require(:item).permit( :item_name, :tag_name ) end endしかし実際に商品を編集・更新をしてみると、、、
param is missing or the value is empty: 'tags_item'のエラーが出てしまい、商品の更新ができませんでした
調べたこと
エラー内容を読んでみると生成したFormオブジェクトの'tag_item_relation'が空になっているとのこと
そして、binding.pryなどを使って調べてみると、そもそもこの記述では'tags_item'が編集・更新では機能していないことが分かります
さらに原因を調べてみると新規投稿(new・create)と編集更新(edit・update)の機能を仕分けしていなかったことだと分かりましたFormオブジェクトで編集更新
今回のエラーの原因はFormオブジェクトに記載したsaveが新規投稿と編集更新で仕分けされていなかったことだと分かりました
/app/form/tags_item.rbclass TagsItem include ActiveModel::Model attr_accessor :item_name, :tag_name with_options presence: true do validates :item_name end def save item = Item.create(item_name: item_name) #ここがcreateアクションのみ tag = Tag.where(tag_name: tag_name).first_or_initialize tag.save TagItemRelation.create(item_id: item.id, tag_id: tag.id) end endこの記述を
/app/form/tags_item.rbclass TagsItem include ActiveModel::Model attr_accessor :item_name, :tag_name with_options presence: true do validates :item_name end # itemがすでに保存されているものか、新規のものかで、PUTとPATCHを分ける delegate :persisted?, to: :item # initializeでFormオブジェクトの値を初期化し、更新の際はdefault_attributesを呼び出す設定 def initialize(attributes = nil, item: Item.new) @item = item attributes ||= default_attributes super(attributes) end def save return if invalid? ActiveRecord::Base.transaction do # mapメソッドを使いsplit_tag_namesをtagの情報に変換 tags = split_tag_names.map { |tag_name| Tag.find_or_create_by!(tag_name: tag_name) } item.update!(item_name: item_name, tags: tags) end rescue ActiveRecord::RecordInvalid false end # formを飛ばす場所を(#createか#updateか)を判別して、切り替えている def to_model item end private attr_reader :item def default_attributes { item_name: item.item_name, tag_name: item.tags.pluck(:tag_name).join(',') } end def split_tag_names tag_name.split(',') end endに変更することで無事にタグ付け機能の編集更新を行うことができました
参考にしたサイト
関連記事
- 投稿日:2021-01-21T16:44:30+09:00
[Rails]DRYに書きたい(可読性、保守性)
[Rails]似たようなコードを1つにまとめたい(パーシャル)
https://railstutorial.jp/chapters/filling_in_the_layout?version=5.1#sec-partials[Rails]DRYなコードを書きたいが、一部分が違う場合
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-edit_form[Rails]タイトルの可変要素をDRYする
https://railstutorial.jp/chapters/static_pages?version=5.1#sec-layouts_and_embedded_ruby
https://qiita.com/shumpeism/items/a0ad5930fa3bc0d24c70[Rails]汎用性があるので異なるControllerでも定義したメソッドを使いたい
継承→application_controller.rb
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-micropost_access_control[Rails]記法一覧
https://qiita.com/gakkie/items/3afcd505c786364aa5fa
https://blog.mothule.com/ruby/ruby-percent-syntax[Ruby]記法一覧
https://railstutorial.jp/chapters/rails_flavored_ruby?version=5.1#cha-rails_flavored_ruby[Rails]キーワード引数とオプション引数の違い
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-users_indexRailsが暗黙的にやってくれること一覧
Railsは慣習に従って、アクションに対応するビューを暗黙的に呼び出します。例えば、showアクションの最後でshow.html.erbを呼び出す、といった具合です。その他
[Rails]rails sがバックグラウンドにあり、ctrl+cで消せない場合
https://qiita.com/kanuu/items/fd6e33fca6ad6a90d059[Rails]ユニーク制約とは?どんなメリットがある?
[Rails]シンボルを使うタイミング
https://uxmilk.jp/25934[Rails]attr_accessor とは?
http://bryankawa.hatenablog.com/entry/2017/01/28/150537非同期で通信がしたい→Ajax,JS
https://railstutorial.jp/chapters/following_users?version=5.1#sec-a_working_follow_button_with_ajax
- 投稿日:2021-01-21T16:43:45+09:00
[Rails]認可、認証、権限関連
[Rails]ログイン済みのユーザーだけにページを表示させたい
Controller
before_action :logged_in_user, only: [:edit, :update]
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-authorization[Rails]自分だけを編集したい
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-requiring_the_right_user[Rails]ユーザーがログインした後、ログイン直前に閲覧していたページヘとリダイレクトさせる機能
→ログインユーザー専用のページのURLにアクセスしたい→ログインする→さっき見てたログイン専用のページに行ける
フレンドリーフォワーディング request.url
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-friendly_forwarding
[Rails]一つ前のURLを返したい(リダイレクトしたい) request.referrer
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-destroying_microposts
[Rails]認可と認証の違い
https://qiita.com/kaysquare1231/items/c4e4736f2a924b03777b
- 投稿日:2021-01-21T16:38:59+09:00
[Rails]セキュリティ系
[Rails]ストロングパラメーター(Strong parameters)
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-revisiting_strong_parameters
[Rails]マスアサインメント
→リクエストのデータをそのままデータベースに保存すること(セキュリティ的に弱い)
https://thinkit.co.jp/story/2015/09/03/6389[Rails]作業を元に戻したい!
rails destroy controller ~
https://railstutorial.jp/chapters/static_pages?version=5.1#sec-generated_static_pages[Rails]アカウントの有効化
https://railstutorial.jp/chapters/account_activation?version=5.1#cha-account_activation[Rails]SSL
ローカルのサーバーからネットワークに流れる前に、大事な情報を暗号化する技術
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-ssl_in_production[Rails]CSRF対策[Controller]
protect_from_forgery with: :exception
https://qiita.com/tanaka7014/items/5b4e2204dc6bec83c90e[Rails]プレースホルダー
https://wa3.i-3-i.info/word118.html[Rails]パスワードをハッシュ化,暗号化して保存したい
https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-adding_a_secure_password
- 投稿日:2021-01-21T16:38:12+09:00
[Rails]DB,ActiveRecord系
[Rails]カラム名を変更したい
https://qiita.com/libertyu/items/93acd8733e34b1d0a63c[Rails]シードを作る(サンプルユーザーをDBにたくさん作りたい)
https://qiita.com/takehanKosuke/items/79a66751fe95010ea5ee
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-sample_users
https://teratail.com/questions/7371[Rails]マイグレーションファイルを削除する
https://qiita.com/tanaka-t/items/cd6aa0526725e88f5024[Rails]ActiveRecordのSQLの可読性をあげたい →Scope
https://qiita.com/ngron/items/14a39ce62c9d30bf3ac3[Rails]複数テーブルにまたがる検索をしたい
https://qiita.com/leon-joel/items/f26556c9e56833983856
https://qiita.com/makitokezuka/items/f13b2e7bad77b5594911
[Rails]複数テーブルにまたがる検索をするときにカラムが被る時[Rails]中間テーブルの命名規則
https://qiita.com/tkawa/items/dc3e313021f32fd91ca6
https://ja.stackoverflow.com/questions/12618/rails%E3%81%AE%E4%B8%AD%E9%96%93%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E5%91%BD%E5%90%8D%E8%A6%8F%E5%89%87%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6[Rails]多対多
https://qiita.com/Kohei_Kishimoto0214/items/cb9a3d3da57708fb52c9
[Rails]多対多のテーブルから検索や更新などしたい
https://qiita.com/Kohei_Kishimoto0214/items/cb9a3d3da57708fb52c9
https://qiita.com/ryutaro9595/items/e021eb789914cead4677[SQL]データモデリング ER図
https://www.atmarkit.co.jp/ait/articles/0604/06/news110.html
https://jp.drinet.co.jp/blog/datamanagement/data_modeling_3minutes[Rails]インデックス
インデックスを作成することでテーブルとは別に検索用に最適化された状態で必要なデータだけがテーブルとは別に保存される。検索用に並び替えをしている上、インデックスを貼ったカラムだけを検索できるので高速検索が可能。デメリットは、テーブルとは別に検索用のテーブルが保存される関係上データの追加に時間がかかること。なぜなら、データを追加するときに2つのテーブルを追加しなければならないから。
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-a_micropost_model
https://www.dbonline.jp/sqlite/index/index1.html
https://ja.wikipedia.org/wiki/%E7%B4%A2%E5%BC%95_%28%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%29[Rails]親を削除した時に子も削除できることをしたい
dependent: :destroy
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-dependent_destroy[Rails]リレーションの時の別テーブルのデータの呼び出し方
→micropost.userなど
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-destroying_microposts[Rails]あるユーザーが同じユーザーを2回以上フォローすることを防ぐこと- 複合キーインデックス
add_index :relationships, [:follower_id, :followed_id], unique: true
の場合だと、follower_idとfollowed_idの組み合わせが必ずユニークであることを保証する仕組み
https://railstutorial.jp/chapters/following_users?version=5.1#sec-a_problem_with_the_data_model[Rails]seedにSecureramdomを導入したい
https://qiita.com/takuyanin/items/5334908b22156ec7290f
- 投稿日:2021-01-21T16:37:13+09:00
[Rails]ルーティング系
[Rails]localhost3000/の状態でトップページを表示したい(3)
→root
https://railstutorial.jp/chapters/static_pages?version=5.1#sec-setting_the_root_route[Rails]RESTfulなルーティング
https://railstutorial.jp/chapters/sign_up?version=5.1#table-RESTful_users
https://qiita.com/NagaokaKenichi/items/0647c30ef596cedf4bf2[Rails]resourceを使ったRESTfulなルーティングにRESTful以外の新しいアクションを追加したい。
https://qiita.com/ebihara99999/items/37afb1486442e7c16a8a
https://railstutorial.jp/chapters/following_users?version=5.1#sec-stats_and_a_follow_form
[Rails]link_toを使ってパラメーターを複数送る方法
https://poyopoyo0.hatenablog.com/entry/2016/02/29/100431[Rails]resourseでネストをする際に、ネスト元もonly:createなどで制限したい
https://railsguides.jp/routing.html#rails%E3%83%AB%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B[Rails]id(並び順整数)をuuid(乱数)に変更したい(localhost:3000/user/ae6cdc44-68cd-4c76-b972-26d8a39b4bbb)みたいにしたい
https://qiita.com/params_bird/items/9e162fdcd9bdc2e42ccd[Rails]ユーザー名(アカウント名)の初期設定を乱数にしたい。
https://teratail.com/questions/285445
username = SecureRandom.urlsafe_base64(10)[Rails]パラメーターを追加で送信したい
hidden_tag
- 投稿日:2021-01-21T16:36:05+09:00
[Rails]Controller系
[Rails]フォームの入力に失敗した時の実装
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-unsuccessful_edits[Rails]Railsのredirect_toにおける_pathと_urlの使い分け(同じようなもの)
https://teratail.com/questions/204077[Rails]部分テンプレートを呼び出したい
render ‘ファイル名’
https://pikawaka.com/rails/render[Rails]Destroyアクションとセキュリティ
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-the_destroy_action[Rails]newとbuildの違い
newメソッドとbuildメソッドはともにインスタンスを生成するが、
buildは自動的にuser_idをセットしてインスタンスを生成することができる。
https://qiita.com/Kaisyou/items/8876f39e12631f4e5154[Rails]CRUD(Create)
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-signup_form[Rails]CRUD(Read)
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-showing_all_users[Rails]CRUD(Destroy)
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-the_destroy_action[Rails]なぜ、HTMLフォームにcreateやdestroyのmethodが記載されてないのに、createされたりdestroyされるの?
→
①URLリクエストをroutesに送る。
②そこで該当コントローラーの該当アクションに指示が行き、そこで事前に自らが記載したcreateやdestroyの処理を行う。
自ら描く事もあれば、resourseで自動で書いてくれる人もいる。
- 投稿日:2021-01-21T16:35:23+09:00
[Rails]View系
[Rails]ページネーション(ページ分割)
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-pagination[Rails]編集フォーム
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-edit_form[Rails]ラクに編集フォームを作りたい
https://qiita.com/Toshimatu/items/dbf4da62ab9951b67aa9[Rails]一覧表示させたい
https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-showing_all_users[Rails]部分テンプレートを呼び出したい
render ‘ファイル名’
https://pikawaka.com/rails/render[Rails]renderとredirect_toの違い
https://qiita.com/january108/items/54143581ab1f03deefa1[Rails]マイクロポストの描画
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-rendering_microposts[Rails]ボタンでアイコンをクリックしてページ遷移したい
https://github.com/neneti/Elily/blob/master/app/views/layouts/_header.html.slim
https://elily.herokuapp.com/
- 投稿日:2021-01-21T16:34:15+09:00
[Rails]Model系
[Rails]ActiveRecordはデータベースはデータベースのレベルでは一意性を保証していない(validateで一意性を保証したとしても)
→indexをつければ解決
https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-uniqueness_validation[Rails]データベースに保存する前に保存する内容を検証したい - バリデーション
https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-user_validations[Rails]文字列などをランダムに出したい。乱数
https://docs.ruby-lang.org/ja/latest/class/SecureRandom.html
- 投稿日:2021-01-21T16:32:57+09:00
[Rails]機能要件の逆引きリファレンス
[Rails]検索機能
https://qiita.com/shin1rok/items/779e581e9d12a92310c3[Rails]画像検索 - 外部ライブラリ Ransack
https://qiita.com/LuckOfWise/items/e020e896e71d47d0c6a4
http://nekorails.hatenablog.com/entry/2017/05/31/173925[Rails]文章投稿機能
https://railstutorial.jp/chapters/user_microposts?version=5.1#cha-user_microposts[Rails]画像を投稿したい
外部ライブラリ - CarrierWave
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-basic_image_upload
→投稿した画像が大きくなる
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-image_validation[Rails]本番環境での画像の保存方法
→クラウドストレージを使うのがいい。
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-image_upload_in_production[Rails]フォロー、フォロワー機能の骨組み
https://railstutorial.jp/chapters/following_users?version=5.1#sec-the_relationship_model[Rails]フォロー、フォロワー一覧ページを作りたい
https://railstutorial.jp/chapters/following_users?version=5.1#sec-following_and_followers_pages[Rails]フォローボタンを作りたい(リダイレクトとAjax)
https://railstutorial.jp/chapters/following_users?version=5.1#sec-a_working_follow_button_the_standard_way
https://railstutorial.jp/chapters/following_users?version=5.1#sec-a_working_follow_button_with_ajax[Rails]タイムライン機能
https://railstutorial.jp/chapters/following_users?version=5.1#sec-the_status_feed[Rails]タイムライン、フィード
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-a_proto_feed[Rails]新規登録をしたらメールアドレスが送られるやつ
https://railstutorial.jp/chapters/account_activation?version=5.1#cha-account_activation[Rails]パスワードを忘れた時に再設定できるやつ
https://railstutorial.jp/chapters/password_reset?version=5.1#cha-password_reset[Rails]成功しました!失敗しました!を知らせてくれるやつ - フラッシュメッセージ
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-signup_error_messages
https://railstutorial.jp/chapters/basic_login?version=5.1#sec-rendering_with_a_flash_message[Rails]ログイン、ログアウト機能
https://railstutorial.jp/chapters/basic_login?version=5.1#cha-basic_login
→外部ライブラリ- devise
https://qiita.com/cigalecigales/items/f4274088f20832252374[Rails]ログインしてブラウザを閉じてもログイン状態を維持したい! - Remember me
https://railstutorial.jp/chapters/advanced_login?version=5.1#sec-remember_me[Rails]サムネイル画像を入れたい
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-a_gravatar_image[Rails]編集画面を表示したり更新したり削除したりしたい
https://railstutorial.jp/chapters/advanced_login?version=5.1#sec-remember_me[Rails]入力する値が期待してるものと違ったら元に戻したい
期待してるものかどうかを判別→正規表現、バリデーション
https://railstutorial.jp/chapters/modeling_users?version=5.1#sec-user_validations
元に戻す→リダイレクト
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-unsuccessful_signups[Rails]いいね機能
↓これでできた↓
https://qiita.com/jaramon/items/248bcb4b56e9fed8fc90
https://qiita.com/krppppp/items/a3e6264f0458d80ca5b7
https://qiita.com/mochikichi321/items/259381d359222b78eca8
https://qiita.com/kenny_0418/items/4bccf641804763306722
https://qiita.com/fuku_tech/items/c9835b7d90bd5effe8ad
https://qiita.com/hayabusa3703/items/2b916e652a1dc85bb6e3
いいね機能の文献
https://qiita.com/rainbow___0/items/a7d66755175b3e8a9636
https://qiita.com/YuitoSato/items/94913d6a349a530b2ea2
https://qiita.com/nojinoji/items/2c66499848d882c31ffa[Rails]アカウントIDを乱数で表示したい(アカウント名 URL rails)
https://qiita.com/awakia/items/c2c790dc51e5b084af10
https://teratail.com/questions/1442
https://blog.takady.net/blog/2015/11/29/rails-routing-with-username-instead-of-id/
https://teratail.com/questions/1442
https://stackoverrun.com/ja/q/1267118
http://vdeep.net/rubyonrails-friendly-id
https://blog.takady.net/blog/2015/11/29/rails-routing-with-username-instead-of-id/[Rails]多階層カテゴリを作る。ancestry
https://qiita.com/Sotq_17/items/120256209993fb05ebac
https://qiita.com/k_suke_ja/items/aee192b5174402b6e8ca検索
https://qiita.com/sconeman/items/fca9efa22536b8b2a9ef
https://qiita.com/sconeman/items/6c839c40371b4ec213bfリプライ
https://qiita.com/krppppp/items/7f9563e08150a008592f
https://qiita.com/sconeman/items/f701474d2c0276b52bfb
https://qiita.com/johnslith/items/8d931b66f72c97c78199
https://qiita.com/EastResident/items/7c96a69be16f5f46c79a
https://iberiko665.hatenablog.com/entry/2018/12/06/031005
https://qiita.com/rockguitar67/items/4fd28cba0c243a8d0ba5
https://qiita.com/kurawo___D/items/d2fefdd329f5310113aaリプライのモーダルフォーム(RailsTutorial拡張)
https://github.com/kotaroooo0/sample-app
https://www.techry.net/blogs/1271
https://qiita.com/sofpyon/items/1e72426598eed745f031リプライをツリー、スレッドにして表示
http://railscasts.com/episodes/262-trees-with-ancestry?language=ja&view=asciicast
https://stackoverflow.com/questions/51326115/reply-a-comment-not-working-using-ancestry-gem-in-rails
https://www.youtube.com/watch?v=I45gHY522Msリプライでリプライ名を対象ユーザーページへのリンクとして表示したい
https://iberiko665.hatenablog.com/entry/2018/12/06/031005オートコンプリート機能
https://qiita.com/swamp09/items/6fb852489b4dc3acfbdd動画アップロード
http://ken992.hatenablog.com/entry/2018/07/04/202616
https://dev.classmethod.jp/articles/ruby-on-rails-carrierwave-ffmpeg/アカウントID(1日)gemがあるらしい
https://qiita.com/awakia/items/c2c790dc51e5b084af10
https://teratail.com/questions/1442
https://blog.takady.net/blog/2015/11/29/rails-routing-with-username-instead-of-id/
https://teratail.com/questions/1442
https://stackoverrun.com/ja/q/1267118
http://vdeep.net/rubyonrails-friendly-id
https://blog.takady.net/blog/2015/11/29/rails-routing-with-username-instead-of-id/タグ機能
自力
https://qiita.com/tobita0000/items/daaf015fb98fb918b6b8
https://qiita.com/you8/items/b2394104c6f9865f5d46
gem
https://qiita.com/YUD96/items/f751010f8a58efaef6ed
https://qiita.com/ddd555/items/e1caa8b73d118822a0a2通知機能
https://qiita.com/nekojoker/items/80448944ec9aaae48d0a
https://qiita.com/tktk0430/items/bdb8fbcf4ce3258b2d41
https://qiita.com/yuto_1014/items/2db1dd4fcd7945b980f7トレンド
管理画面
https://qiita.com/enomotodev/items/5f6d9348207124a41bf9
- 投稿日:2021-01-21T16:04:43+09:00
[Rails] CircleCIでRubocop・RSpecを実施しCapistranoを走らせAWS(EC2)に自動でプロイする方法
はじめに
CircleCIをポートフォリオに組み込みデプロイの自動化はしたものの、テストの自動化は行なっていなかったので、そちらの実装ができたので、記事にしていこうと思います。
前提
- テストを実装済み(RSpec)
- Rubocop導入済み
- EC2にデプロイ済み
- 開発環境にDockerを用いている
開発環境
- Ruby 2.6.5
- Rails6
- MySQL 5.6.50
- Docker
- docker-compose
- Capistrano(自動デプロイツール)
完成コード
.circleci/config.ymlversion: 2.1 orbs: ruby: circleci/ruby@1.1.0 jobs: build: docker: - image: circleci/ruby:2.6.5-node-browsers environment: BUNDLER_VERSION: 2.1.4 steps: - checkout - ruby/install-deps test: parallelism: 3 docker: - image: circleci/ruby:2.6.5-node-browsers environment: DB_HOST: 127.0.0.1 RAILS_ENV: test BUNDLER_VERSION: 2.1.4 - image: circleci/mysql:8.0 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_ALLOW_EMPTY_PASSWORD: "true" MYSQL_ROOT_HOST: "%" steps: - checkout - ruby/install-deps - run: yarn install - run: mv config/database.yml.ci config/database.yml - run: name: Wait for DB command: dockerize -wait tcp://localhost:3306 -timeout 1m - run: bundle exec rake db:create - run: bundle exec rake db:schema:load - run: name: RuboCop command: bundle exec rubocop - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3 - run: mkdir ~/rspec - run: command: bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml when: always - store_test_results: path: ~/rspec deploy: docker: - image: circleci/ruby:2.6.5-node-browsers environment: BUNDLER_VERSION: 2.1.4 steps: - checkout - ruby/install-deps - add_ssh_keys: fingerprints: "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" - deploy: name: Capistrano deploy command: bundle exec cap production deploy workflows: version: 2 build_accept_deploy: jobs: - build - test: requires: - build - deploy: requires: - test filters: branches: only: master解説をすると、環境を指定するところでは
test
環境を指定します。
そして、DBもtest
環境に合わせるためconfigディレクトリ
にdatabase.yml.ciファイル
を作成します。作成したら以下のように編集しましょう。
config/database.yml.citest: adapter: mysql2 encoding: utf8 pool: 5 username: 'root' port: 3306 host: '127.0.0.1' database: ci_testこのように
test
環境用のDBを設定できればCircleCIでの環境構築は終了です。ここからは実際にテストをするための準備に取り掛かります。コードでいうと
test
(testジョブ
)の部分に当たります。
主に公式を参考にして作業しましたので、公式も参考にしてください。また、その際にCircleCI用にRSpecの
rspec_junit_formatter
というGemをインストールする必要があります。
こちらも公式に書いてあります。Gemfilegroup :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 # rspec_junit_formatterをgroup :test do内に記述 gem 'rspec_junit_formatter' gem 'webdrivers' end忘れずに
bundle install
をしてサーバーの再起動を行いましょう。これで準備が整いました。
test
の部分を見ていきましょう。testジョブ
.circleci/config.ymltest: parallelism: 3 docker: - image: circleci/ruby:2.6.5-node-browsers environment: DB_HOST: 127.0.0.1 RAILS_ENV: test BUNDLER_VERSION: 2.1.4 - image: circleci/mysql:8.0 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_ALLOW_EMPTY_PASSWORD: "true" MYSQL_ROOT_HOST: "%" steps: - checkout - ruby/install-deps - run: yarn install - run: mv config/database.yml.ci config/database.yml - run: name: Wait for DB command: dockerize -wait tcp://localhost:3306 -timeout 1m - run: bundle exec rake db:create - run: bundle exec rake db:schema:load - run: name: RuboCop command: bundle exec rubocop - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3 - run: mkdir ~/rspec - run: command: bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml when: always - store_test_results: path: ~/rspecこの記述でテストを実行することができます。
ただ、自分の場合はテスト時に以下のエラーが出ました。
Webpacker::Manifest::MissingEntryError
というエラーが出て、コンパイルができないとRSpecさんに怒られてしまいました。ということで
steps
でyarn install
コマンドを実行するように追記しました。.circleci/config.ymlsteps: - checkout - ruby/install-deps - run: yarn install - run: mv config/database.yml.ci config/database.yml - run: name: Wait for DB command: dockerize -wait tcp://localhost:3306 -timeout 1m - run: bundle exec rake db:create - run: bundle exec rake db:schema:load - run: name: RuboCop command: bundle exec rubocop - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3 - run: mkdir ~/rspec - run: command: bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml when: always - store_test_results: path: ~/rspecこれでテストが上手く通れば、デプロイが自動で行われます。
成功するとGUI上でこのように表示されます。ちなみに、このテスト実行時、Rubocopでのエラーが起こることがあるようです。
その場合は
rubocop.yml
に記述を加えます。rubocop.ymlAllCops: TargetRubyVersion: # 自分のRubyのバージョンこのように記述するとエラーが解決できるようです。
詳しくは下記の記事を参考にしてみてください。ちなみに、
.circleci/config.yml
の記述などは以下の記事も非常にわかりやすいので参考にしてみてください。ということで、残すはデプロイということなので、そこも見ていきましょう。
deployジョブ
.circleci/config.ymldeploy: docker: # 自分のRubyのバージョンを指定 - image: circleci/ruby:2.6.5-node-browsers environment: # ローカルでインストールされているbundlerのバージョンを指定 BUNDLER_VERSION: 2.1.4 steps: - checkout - ruby/install-deps - add_ssh_keys: fingerprints: "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" - deploy: name: Capistrano deploy command: bundle exec cap production deployこの辺は僕も記事にしているのでそちらのほうが参考になるかなと思います。ここはほぼ公式どおりなのでそちらを読み進めてもらったほうがいいかなと、下記を参考にしてみてください。
Workflows
.circleci/config.ymlworkflows: version: 2 build_accept_deploy: jobs: - build - test: requires: - build - deploy: requires: - test filters: branches: only: masterGitのmasterブランチにpush・mergeされるたびにCircleCIが走って、CI/CDしてくれるようルールを決めているような感じです。
以上で、RailsとAWSのCI/CDの実装は完了です。
参考になれば幸いです。参考文献
CircleCI 公式ドキュメント テスト メタデータの収集
- 投稿日:2021-01-21T15:44:26+09:00
axios では xhr? が効かない
自分用メモ。
axiosはAjaxで通信するときに、リクエストヘッダーに
X-Requested-With
を付けません。参照: https://github.com/axios/axios/issues/1322
なので、Railsのxhr?メソッドは偽になります。
if request.xhr? # axiosだと効かない endxhr?メソッドを使いたければ、JavaScript側でaxiosのヘッダーに
X-Requested-With
を追加する設定が必要です。Axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';あるいは、Rails側で
X-Requested-With
がなくても動くようにします。if params[:format] == 'json' # Ajaxの場合の処理 end
- 投稿日:2021-01-21T15:42:27+09:00
Railsによるfollow機能の実装
はじめに
Railsを使ってfollow機能を実装する中で気づいたことなどを自分用のメモとして手順と共に残しておこうと思い記事を書きました。間違っているところなどありましたらご指摘いただけると助かります!
Follow機能実装にあたって行う手順
- Followモデルを作り、dbにfollowsテーブルを追加
- 各モデルで関連付けを実装、フォロワー・フォローしている人を簡単に取得できるメソッドを定義する。
- 各controller, viewでそれらを表示
おおまかにはこんな流れです。基本的にはRailsチュートリアル第4版を参考にしています。
Followsモデルを追加
terminalbin/rails g model Follow follower_id:integer followed_id:integer上のように、rails g のコマンドでモデルを作ります。今回は、あるユーザーから見て、フォローされている人のidを格納するfollower_idカラム、そのユーザー自身のidを格納するfollowed_idカラム、を定義しました。
そうすると、migrationファイルが生成されるので、terminalbin/rails db:migrateを実行します。これでデータベースへの反映は完了です。
各モデルでの関連付けの実装
今回は、Followモデルには User モデルのidのみを格納するので、Userモデルとの関連付けのみを行います。下のコードは、あるユーザーがフォローしているユーザーを取得するために行う関連付けの例です。
User.rbhas_many :active_follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy has_many :following, through: :active_follows, source: :followedFollow.rbbelongs_to :follower, class_name: "User"関連付けについては以下のような規則で行います。
1. model同士の関係性を1対1なのか、1対多なのか考える。
2. 1対1の場合はbelongs_to, 1対多の場合はhas_many, で関連付けする。今回であれば、Userモデルから見た場合、Followという行為は何回でも行えるものなので、1ユーザーに対して多数のFollowの情報が存在します。よって、1対多の関係です。
反対に、Followモデルから見た場合、一つのFollowレコードに対して、フォローしているユーザーは一人、フォローされているユーザーも一人です。よって、1対1の関係です。(ただし、Followモデルの中のfollower_idが取得したいのか、followed_idが取得したいのか、ということは関連付けを一つ行っただけではわかりません。なので、今回はフォローする側、される側、の二つに分けて関連付けを行います。初め僕はここがよくわからなかったので注釈としておきます)
また、関連付けでは、次の項目を指定することができます。
- 関連付けをするメソッドの名前
- 関連づけるクラスの名前
- 参照する外部キーの名前
- 関連付け先のモデルとの依存関係
これは、以下のように対応しています。
User.rbhas_many :active_follows, #ここ1 class_name: "Follow", #ここ2 foreign_key: "follower_id" #ここ3 dependent: :destroy #ここ41で、Userモデルのインスタンスに対して使う関連付け名(要するにメソッド名)を定義します。
2で、そのメソッドを用いたときどのクラスを参照するか指定します。今回はFollowモデルとの関連付けなのでFollowを指定しています。
3で、Followモデルのどのカラムを参照するか指定します。今回はあるユーザーがフォローしているユーザーを取得したいので、外部キーとしてfollower_idを指定します。
4で、そのモデルのインスタンスが削除された場合、紐づいているモデルの対応するカラムも削除するかどうかを指定します。ユーザーを削除した場合、フォロー情報も消去したいのでdependent: :destroyを指定します。ここまでUserモデル側での関連付けについて説明しましたが、Followモデル側では次のコードのみで済みます。
Follow.rbbelongs_to : follower, class_name: "User"これは、Railsの自動的な推測によります。こちらでは、1と2の指定のみで、誰がフォローしているかの情報をfollowerというメソッドで取り出せるようになります。class名を指定すると、そのクラスの主キーがfollower_idと一致するユーザーを取得してくれます。
最後に、今のままではUserインスタンスに対してactive_followsを用いてもFollowテーブルの情報が返ってくるのみです。フォローしているユーザーまで返してくれると便利なので、following関連付けを追加します。それが以下の部分です。
User.rbhas_many :following, through: active_follows, source: :followedこれは、followingという名前の関連付け(メソッド)を実行すれば、active_followsというメソッドを実行して、さらにそれにより得られたFollowテーブルのデータたちのfollowed_id というカラムのidを持つユーザーを取得してね、という意味になります。sourceに指定したfollowedの _id の部分はRailsによって補完されます。
以上で、Userモデルのインスタンスからフォロワーを取得してくる関連付けが定義できました!長々とわかりづらく書いてしまい申し訳ありません・・・
各controller,viewでの表示
これは他のところでも用いている方法と全く同じなので割愛します。取得した@userなどのインスタンス変数に対して先ほど定義したfollowingメソッドを実行し、レイアウトを整えるのみです。
終わりに
チュートリアル1周目にはあまり理解できていなかった部分を、ポートフォリオを作っている最中にしっくりきたので言葉に起こしておきました。自分なりの理解なのでわかりづらいところ、間違っているところなどあると思います。参考にされる際はその点御留意くださりますと幸いです。
- 投稿日:2021-01-21T14:30:32+09:00
RSpecでpry-byebug(binding.pry)が使えなかった時の対応(初歩)
環境
Mac OS X
Ruby: 2.7.1
Rails: 6.0.3.4状況
RSpecでテスト書いてるときに、hogehoge.errors[:hoge]の中身ってどうなってるのか気になることがあった。
そこでpry-byebugを使って確認しようと、テストコードの該当箇所にbinding.pryを入れてキャッチしようとしたが、キャッチできずにそのままテストが進んでしまった。原因
pry-byebugのgemがdevelopmentにしか入っていなかったから。
Gemfilegroup :development do gem 'pry-byebug' end対応
pry-byebugのgemをtest環境に入れる(自分の場合はdevelopment環境でも使いたいので以下の場所にいれた)
Gemfilegroup :development, :test do gem 'pry-byebug' end結果
該当箇所で処理がとまり、pry-byebugが使えるようになった!
感想
開発環境と本番環境の違いはherokuなどを使っていたのでわかってたのですが、開発環境とテスト環境で違うという感覚が無かったので勉強になりました...
- 投稿日:2021-01-21T14:15:26+09:00
[Rails] GoogleMapを使って、マーカーが立っている位置をDBに保存する!
前提
・Railsのアプリケーションであること
・記事作成機能が存在すること
・GoogleMapを自分のアプリケーション上で表示することができていること
※下記記事などが非常に参考になると思います。https://qiita.com/nagaseToya/items/e49977efb686ed05eadb
目標
記事作成の際、マップにマーカーを1つだけ立てられるようにし、その位置情報をDBに保存すること。
マーカーの立て方としては以下を想定。・マップをクリック
・位置を検索それではやっていきましょう!
gemのインストール ※いらない方はスキップしてください
Gemfilegem 'geocoder' gem 'gon'※この記事においてはこの2つのgemは使用しません。しかし、これらのgemが入っているという前提で進めていきます。
geocoderは便利なメソッドが豊富です。
RailsでGoogleMapを使用のであれば入れておいたほうが良いです。
gonはController内でセットした変数をJavascript内で使う事ができます。
DBに保存した位置情報を記事詳細画面で表示させる際に非常に便利です。geocoder
https://github.com/alexreisner/geocodergon
https://github.com/gazay/gonこれらを記述した後、bundle install します。
マップの情報保存用テーブル作成
指定した緯度、経度を保存するテーブルを作成します。
まず、マイグレーションファイルを作成しましょう。
マイグレーションファイルはこんな感じにします。
私の場合は、記事と地図を関連付けさせたいのでこのようになっています。
マップ単品の方は
t.references :article, null: false, foreign_key: true
の部分はいらないかと思います。timestamp_xxx.rb(マイグレーションファイル)class CreateMaps < ActiveRecord::Migration[6.0] def change create_table :maps do |t| t.references :article, null: false, foreign_key: true t.string :address t.float :latitude t.float :longitude t.timestamps end end endその後、rails db:migrate します。
モデルの関連付け
関連付けさせなくて良い方はスキップしても大丈夫です。
map.rbclass Map < ApplicationRecord belongs_to :article geocoded_by :address after_validation :geocode endarticle.rbhas_one :map, dependent: :destroyマップの表示
表示だけならこれだけでできると思います。
〇〇.html.erb<div id='map'></div> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script> <script> let map function initMap (){ myLatLng = {lat: 35.68090045006303, lng: 139.76690798417752} map = new google.maps.Map(document.getElementById('map'), { center: myLatLng, zoom: 12 }); </script>マップのクリックしたところにマーカーを立てることができるようにする
記事作成と同時にクリックした箇所の経度、緯度を保存できるようにします。
また、マーカを削除できるボタンも追加しました。_article_form.html.erb<div id="article_form" class="field"> <%= f.label :title, "タイトル" %> <%= f.text_area :title %> マップ <div id='map'></div> <%= f.fields_for :map, @article.build_map do |map| %> <%= map.hidden_field :latitude %> <%= map.hidden_field :longitude %> <% end %> <%= f.label :content, "本文" %> <%= f.rich_text_area :content,placeholder:"入力してください" %> <%= f.label :tag_list %> <%= f.file_field :image, accept: "image/jpeg,image/gif,image/png" %> </div> <div id="article_button"><%= f.submit "投稿!",class:"btn"%></div> <% end %> <button id="del" class="btn" onclick="deleteMarker();">マーカー削除</button> <script> var marker var myLatLng var map var map_lat var map_lng function initMap(){ myLatLng = {lat: 35.68090045006303, lng: 139.76690798417752} marker = new google.maps.Marker(); map_lat = document.getElementById('article_map_latitude') map_lng = document.getElementById('article_map_longitude') map = new google.maps.Map(document.getElementById('map'), { center: myLatLng, zoom: 8 }); google.maps.event.addListener(map, 'click', mylistener); //クリックしたときの処理 function mylistener(event){ //markerの位置を設定 //event.latLng.lat()でクリックしたところの緯度を取得 marker.setPosition(new google.maps.LatLng(event.latLng.lat(), event.latLng.lng())); //marker設置 marker.setMap(map); map_lat.value = event.latLng.lat(); map_lng.value = event.latLng.lng(); } } function deleteMarker(){ marker.setMap(null); map_lat.value = ""; map_lng.value = ""; } </script> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script> 30下記のコードによってarticleと関連付けたmapにデータを渡すことができます。
<%= f.fields_for :map, @article.build_map do |map| %> <%= map.hidden_field :latitude %> <%= map.hidden_field :longitude %> <% end %>また、これらに値を入れるコードはこの部分です。
map_lat = document.getElementById('article_map_latitude') map_lng = document.getElementById('article_map_longitude') //↑map.hidden_fieldによって生成された<input>のidです。 //人によって違うかもしれないのでブラウザの開発者モードで確認してください。 //〜〜省略〜〜 map_lat.value = event.latLng.lat(); map_lng.value = event.latLng.lng();そして、値をコントローラに渡すため、StrongParameterの設定も必要です。
binding.pryなどで、どのようなparamsが渡ってきているか確認しておいたほうが良いかと思います。article_controller.rbdef article_params params.require(:article) .permit(:content, :title, map_attributes: [:id, :latitude, :longitude]) endこれを保存するコードはこちらです。
article_controller.rbdef create @article = current_user.articles.build(article_params) if @article.save latitude = params[:article][:map][:latitude] longitude = params[:article][:map][:longitude] unless latitude.empty && longitude.empty? @map = @article.build_map( latitude: latitude, longitude: longitude ) @map.save end #〜〜〜〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜 end位置検索でもマーカーを立てることができるようにする
この場合、GoogleMapAPIだけでなく、Geocoding APIも必要になってきます。
紆余曲折あり、最終的に完成したのがこちらです。<div class="row"> <div class="col s12 m10 push-m1"> <div class="card"> <div class="card-content article-card"> <%= form_with(model:@article,local: true,class:"margin-30") do |f|%> <%= render 'shared/error_messages',object: f.object %> <div id="article_form" class="field"> <div class="input-field"> <%= f.text_field :title,class: "materialize-textarea" %> <%= f.label :title, "タイトル" %> </div> <div class="input-field"> <%= f.text_field :tag_list, value: @article.tag_list.join(','), class: "materialize-textarea" %> <%= f.label :tag_list,"タグ ※コンマ区切りで記入してください" %> </div> <!-- 追加したイベント --> <div class="input-field"> <input type="text" id="address" placeholder="地名、施設名などを入力するか、地図をクリックしてマーカーを立ててください"> <label>場所</label> <a class="btn" onclick="codeAddress()">地図検索</a> <a id="del" class="btn marker-delete right" onclick="deleteMarker()"> <i class="fas fa-map-marker-alt fas-2x" style="color:red"></i>削除 </a> </div> <!-- ここまで --> <div id='map' class="margin-t-b-14"></div> <%= f.fields_for :map, @article.build_map do |map| %> <%= map.hidden_field :latitude %> <%= map.hidden_field :longitude %> <% end %> <%= f.rich_text_area :content,placeholder:"入力してください",class: "materialize-textarea" %> <%= f.label :content, "本文" %> <%= f.label :thumbnail, "サムネイル" %> <%= f.file_field :thumbnail, accept: "image/jpeg,image/gif,image/png",class:"file_field" %> <div id="article_button"><%= f.submit "投稿!",class:"btn col s6 m6 article-form-btn push-s3 push-m3"%></div> </div> <% end %> </div> </div> </div> </div> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script> <script> var marker var myLatLng var map_lat var map_lng var geocoder var map_result let map function initMap (){ myLatLng = {lat: 35.68090045006303, lng: 139.76690798417752} map_lat = document.getElementById('article_map_latitude') map_lng = document.getElementById('article_map_longitude') marker = new google.maps.Marker(); map = new google.maps.Map(document.getElementById('map'), { center: myLatLng, zoom: 12 }); google.maps.event.addListener(map, 'click', mylistener); //クリックしたときの処理 function mylistener(event){ marker.setPosition(new google.maps.LatLng(event.latLng.lat(), event.latLng.lng())); marker.setMap(map); console.log(event.latLng.lat(), event.latLng.lng()); map_lat.value = event.latLng.lat(); map_lng.value = event.latLng.lng(); } } function deleteMarker(){ marker.setMap(null); map_lat.value = ""; map_lng.value = ""; } //追加した関数 function codeAddress(){ geocoder = new google.maps.Geocoder() let inputAddress = document.getElementById('address').value; geocoder.geocode( { 'address': inputAddress, 'region': 'jp' }, function(results, status) { if (status == 'OK') { map.setCenter(results[0].geometry.location); map_result = results[0].geometry.location; map_lat.value = map_result.lat(); map_lng.value = map_result.lng(); marker.setPosition(new google.maps.LatLng(map_result.lat(), map_result.lng())); marker.setMap(map); console.log(map_lat.value,map_lng.value); } else { alert('該当する結果がありませんでした'); initMap(); } }); } </script>随分長いコードになってしまいました。
しかし、実際は関数とイベントが1つ増えただけなのでその部分を見てもらえればわかるかと思います!
これによって、・地図をクリック
・位置を検索
することで地図上にマーカーを立て、その位置情報をDBに保存することができるようになりました!
これらを利用する方法についてはまた後日記事を書こうかと思います。
- 投稿日:2021-01-21T14:15:26+09:00
[Rails6] GoogleMapを使って、マーカーが立っている位置をDBに保存する!
前提
・Railsのアプリケーションであること
※私のRailsのバージョンは6.0.3です
・記事作成機能が存在すること
・GoogleMapを自分のアプリケーション上で表示することができていること
※下記記事などが非常に参考になると思います。https://qiita.com/nagaseToya/items/e49977efb686ed05eadb
目標
記事作成の際、マップにマーカーを1つだけ立てられるようにし、その位置情報をDBに保存すること。
マーカーの立て方としては以下を想定。・マップをクリック
・位置を検索(GeocodingAPIを使用)それではやっていきましょう!
gemのインストール ※いらない方はスキップしてください
Gemfilegem 'geocoder' gem 'gon'※この記事においてはこの2つのgemは使用しません(次の記事で使用予定)。しかし、これらのgemが入っているという前提で進めていきます。
geocoderは便利なメソッドが豊富です。
RailsでGoogleMapを使用のであれば入れておいたほうが良いです。
gonはController内でセットした変数をJavascript内で使う事ができます。
DBに保存した位置情報を記事詳細画面で表示させる際に非常に便利です。geocoder
https://github.com/alexreisner/geocodergon
https://github.com/gazay/gonこれらを記述した後、bundle install します。
マップの情報保存用テーブル作成
指定した緯度、経度を保存するテーブルを作成します。
まず、マイグレーションファイルを作成しましょう。
私の場合は、記事と地図を関連付けさせたいのでこのようになっています。
マップ単品の方は
t.references :article, null: false, foreign_key: true
の部分はいらないかと思います。timestamp_xxx.rb(マイグレーションファイル)class CreateMaps < ActiveRecord::Migration[6.0] def change create_table :maps do |t| t.references :article, null: false, foreign_key: true t.string :address t.float :latitude t.float :longitude t.timestamps end end endその後、rails db:migrate します。
モデルの関連付け
関連付けさせなくて良い方はスキップしても大丈夫です。
map.rbclass Map < ApplicationRecord belongs_to :article geocoded_by :address after_validation :geocode endarticle.rbhas_one :map, dependent: :destroyマップの表示
表示だけならこれだけでできると思います。
〇〇.html.erb<div id='map'></div> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script> <script> let map function initMap (){ myLatLng = {lat: 35.68090045006303, lng: 139.76690798417752} map = new google.maps.Map(document.getElementById('map'), { center: myLatLng, zoom: 12 }); </script>マップ上でクリックしたところにマーカーを立てることができるようにする
記事作成の際に、マップ上でクリックした箇所にマーカーを立てられるようにします。
また、マーカーが立っている箇所の経度、緯度を保存できるようにします。
ついでにマーカーを削除できるボタンも追加しました。_article_form.html.erb<div id="article_form" class="field"> <%= f.label :title, "タイトル" %> <%= f.text_area :title %> マップ <div id='map'></div> <%= f.fields_for :map, @article.build_map do |map| %> <%= map.hidden_field :latitude %> <%= map.hidden_field :longitude %> <% end %> <%= f.label :content, "本文" %> <%= f.rich_text_area :content,placeholder:"入力してください" %> <%= f.label :tag_list %> <%= f.file_field :image, accept: "image/jpeg,image/gif,image/png" %> </div> <div id="article_button"><%= f.submit "投稿!",class:"btn"%></div> <% end %> <button id="del" class="btn" onclick="deleteMarker();">マーカー削除</button> <script> var marker var myLatLng var map var map_lat var map_lng function initMap(){ myLatLng = {lat: 35.68090045006303, lng: 139.76690798417752} marker = new google.maps.Marker(); map_lat = document.getElementById('article_map_latitude') map_lng = document.getElementById('article_map_longitude') map = new google.maps.Map(document.getElementById('map'), { center: myLatLng, zoom: 8 }); google.maps.event.addListener(map, 'click', mylistener); //クリックしたときの処理 function mylistener(event){ //markerの位置を設定 //event.latLng.lat()でクリックしたところの緯度を取得 marker.setPosition(new google.maps.LatLng(event.latLng.lat(), event.latLng.lng())); //marker設置 marker.setMap(map); map_lat.value = event.latLng.lat(); map_lng.value = event.latLng.lng(); } } function deleteMarker(){ marker.setMap(null); map_lat.value = ""; map_lng.value = ""; } </script> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script> 30下記のコードによってarticleと関連付けたmapにデータを渡すことができます。
<%= f.fields_for :map, @article.build_map do |map| %> <%= map.hidden_field :latitude %> <%= map.hidden_field :longitude %> <% end %>また、これらに値を入れるコードはこの部分です。
map_lat = document.getElementById('article_map_latitude') map_lng = document.getElementById('article_map_longitude') //↑map.hidden_fieldによって生成された<input>のidです。 //人によって違うかもしれないのでブラウザの開発者モードで確認してください。 //〜〜省略〜〜 map_lat.value = event.latLng.lat(); map_lng.value = event.latLng.lng();そして、値をコントローラに渡すため、StrongParameterの設定も必要です。
binding.pryなどで、どのようなparamsが渡ってきているか確認しておいたほうが良いかと思います。article_controller.rbdef article_params params.require(:article) .permit(:content, :title, map_attributes: [:id, :latitude, :longitude]) endこれを保存するコードはこちらです。
article_controller.rbdef create @article = current_user.articles.build(article_params) if @article.save latitude = params[:article][:map][:latitude] longitude = params[:article][:map][:longitude] unless latitude.empty && longitude.empty? @map = @article.build_map( latitude: latitude, longitude: longitude ) @map.save end #〜〜〜〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜 end位置検索でもマーカーを立てることができるようにする
この場合、GoogleMapAPIだけでなく、Geocoding APIも必要になってきます。
紆余曲折あり、最終的に完成したのがこちらです。<div class="row"> <div class="col s12 m10 push-m1"> <div class="card"> <div class="card-content article-card"> <%= form_with(model:@article,local: true,class:"margin-30") do |f|%> <%= render 'shared/error_messages',object: f.object %> <div id="article_form" class="field"> <div class="input-field"> <%= f.text_field :title,class: "materialize-textarea" %> <%= f.label :title, "タイトル" %> </div> <div class="input-field"> <%= f.text_field :tag_list, value: @article.tag_list.join(','), class: "materialize-textarea" %> <%= f.label :tag_list,"タグ ※コンマ区切りで記入してください" %> </div> <!-- 追加したイベント --> <div class="input-field"> <input type="text" id="address" placeholder="地名、施設名などを入力するか、地図をクリックしてマーカーを立ててください"> <label>場所</label> <a class="btn" onclick="codeAddress()">地図検索</a> <a id="del" class="btn marker-delete right" onclick="deleteMarker()"> <i class="fas fa-map-marker-alt fas-2x" style="color:red"></i>削除 </a> </div> <!-- ここまで --> <div id='map' class="margin-t-b-14"></div> <%= f.fields_for :map, @article.build_map do |map| %> <%= map.hidden_field :latitude %> <%= map.hidden_field :longitude %> <% end %> <%= f.rich_text_area :content,placeholder:"入力してください",class: "materialize-textarea" %> <%= f.label :content, "本文" %> <%= f.label :thumbnail, "サムネイル" %> <%= f.file_field :thumbnail, accept: "image/jpeg,image/gif,image/png",class:"file_field" %> <div id="article_button"><%= f.submit "投稿!",class:"btn col s6 m6 article-form-btn push-s3 push-m3"%></div> </div> <% end %> </div> </div> </div> </div> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API'] %>&callback=initMap" async defer></script> <script> var marker var myLatLng var map_lat var map_lng var geocoder var map_result let map function initMap (){ myLatLng = {lat: 35.68090045006303, lng: 139.76690798417752} map_lat = document.getElementById('article_map_latitude') map_lng = document.getElementById('article_map_longitude') marker = new google.maps.Marker(); map = new google.maps.Map(document.getElementById('map'), { center: myLatLng, zoom: 12 }); google.maps.event.addListener(map, 'click', mylistener); //クリックしたときの処理 function mylistener(event){ marker.setPosition(new google.maps.LatLng(event.latLng.lat(), event.latLng.lng())); marker.setMap(map); console.log(event.latLng.lat(), event.latLng.lng()); map_lat.value = event.latLng.lat(); map_lng.value = event.latLng.lng(); } } function deleteMarker(){ marker.setMap(null); map_lat.value = ""; map_lng.value = ""; } //追加した関数 function codeAddress(){ geocoder = new google.maps.Geocoder() let inputAddress = document.getElementById('address').value; geocoder.geocode( { 'address': inputAddress, 'region': 'jp' }, function(results, status) { if (status == 'OK') { map.setCenter(results[0].geometry.location); map_result = results[0].geometry.location; map_lat.value = map_result.lat(); map_lng.value = map_result.lng(); marker.setPosition(new google.maps.LatLng(map_result.lat(), map_result.lng())); marker.setMap(map); console.log(map_lat.value,map_lng.value); } else { alert('該当する結果がありませんでした'); initMap(); } }); } </script>随分長いコードになってしまいました。
しかし、実際は関数とイベントが1つ増えただけなのでその部分を見てもらえればわかるかと思います!
これによって、マップをクリックor位置を検索することで地図上にマーカーを立て、その位置情報をDBに保存することができるようになりました!
これらを利用する方法についてはまた後日記事を書こうかと思います。
- 投稿日:2021-01-21T13:43:12+09:00
Uncaught Error: Cannot find moduleが出た話
こんにちは。
現在JavaScriptを勉強中です。
今回はUncaught Errorに出くわしたのでその話をしたいと思います。結論から申し上げますと、すごくしょうもない理由でした(笑)
経緯
Ruby on Rails アプリケーションにでJavaScriptを実装している段階で、すでに作成されているapplication.jsに読み込ませるJavaScriptファイルを記述しました。
ローカルサーバーにて、挙動を確認しようとしたところ、下記のようなエラーが出ました。application.js:10 Uncaught Error: Cannot find module '../sample.js' at webpackMissingModule (application.js:10) at Object../app/javascript/packs/application.js (application.js:10) at __webpack_require__ (bootstrap:19) at bootstrap:83 at bootstrap:83 webpackMissingModule @ application.js:10 ./app/javascript/packs/application.js @ application.js:10 __webpack_require__ @ bootstrap:19 (anonymous) @ bootstrap:83 (anonymous) @ bootstrap:83仮説
①webpackMissingModuleとあるので、またgem関連でエラーが生じているのかなと思い、bundle installを実施するも改善なし。
②読み込ませたいJavaScriptファイル内の記述がおかしいのかなとも考えましたが、そもそも読み込まないエラーなのであればその線は無い・・・。
③エラー内容をよく見ると、webpackMissingModuleの後に、(application.js:10)
とあり、application.jsの10行目がおかしいのでは?と捉えられる・・・。解消方法
結論としては、読み込ませるJavaScriptファイルの配置ミスでした。
application.jsの10行目を見ると、私はこのように記述をしていました。
require("../sample")それに対して、実際のsample.jsファイルはこのような配置になっておりました。
app
javascript
channels
packs
sample.jsファイル配置の書き方、見にくかったらすみません・・・。
上記のようにpacksのなかにsample.jsが存在しており、かつapplication.js内での読み込ませる記述が
("../sample")
となっていたため、今回のエラーが発生したようです。したがって、sample.jsファイルを1つ上位ディレクトリ、javascriptディレクトリ直下に配置し直したところ、エラーは改善されました。
考察
今回私は何も考えずにパスの指定を
require("../sample")としてしまいました。
このパスの指定における .(ドット)と..(ドットドット)の意味をしっかり把握しておりませんでした。
.(ドット)→現在のディレクトリを表す。今回の場合であれば、application.jsが存在するディレクトリ、packsになります。
..(ドットドット)→現在のディレクトリより1つ上位のディレクトリを表す。今回の場合、application.jsが存在するディレクトリの1つ上位、javascriptディレクトリになります。パスの指定というのは色々複雑で混乱してしまいますね。
とてもしょうもない理由で発生したエラーでしたが、誰かの参考になればとても幸いです。ご覧いただきありがとうございました!
- 投稿日:2021-01-21T12:40:50+09:00
rails kaminariのページネーションについて
@client.event
async def on_message(message):
"""メンバー募集 (.rect@数字)"""
if message.content.startswith(".rect"):
mcount = int(message.content[6:len(message.content)])
text= "あと{}人 募集中\n"
revmsg = text.format(mcount)
frelist = []
msg = await message.channel.send(revmsg)await msg.add_reaction("✅") await msg.add_reaction("⬅") await msg.add_reaction('✖') while len(frelist) < int(message.content[6:len(message.content)]): target_reaction = await client.wait_for(message=msg) if target_reaction.user != msg.author: if target_reaction.reaction.emoji == "✅": if target_reaction.user.name in frelist: frelist.remove(target_reaction.user.name) mcount += 1 await client.edit_message(msg, text.format(mcount) + '\n'.join(frelist))
- 投稿日:2021-01-21T12:30:11+09:00
SystemSpec 実行時のunable to connect to chromedriverエラー
#はじめに
SystemSpecを実行したところ以下のエラーが発生。解決した手順を残しておきます。
環境
windows10 Home
ruby 2.7.0
Rails 6.0.3.4
ubuntu 18.04
1.1) Failure/Error: visit new_user_session_path Selenium::WebDriver::Error::WebDriverError: unable to connect to chromedriver 127.0.0.1:9515 # ./spec/system/users_spec.rb:9:in `block (2 levels) in <main>' 1.2) Failure/Error: raise Error::WebDriverError, cannot_connect_error_text Selenium::WebDriver::Error::WebDriverError: unable to connect to chromedriver 127.0.0.1:9515
#試したこと
ターミナルにGoogle chromeをインストール
下の記事を参考にchromeDriverインストールされているか確認、インストールされていなかったのでインストール。
UbuntuにChromeをインストールする#インストールされていないことを確認 apt list --installed google* #google.listの最終行に追加 sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' #登録された事を確認 ls -l /etc/apt/sources.list.d >-rw-r--r-- 1 root root 55 Jan 21 09:45 google.list cat /etc/apt/sources.list.d/google.list >deb http://dl.google.com/linux/chrome/deb/ stable main #公開鍵をダウンロードして、更に、公開鍵をapt-keyで登録 sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - #パッケージリストを最新の状態に sudo apt update #インストール sudo apt-get install google-chrome-stable
別のエラーが発生
capybara-webkitがインストールされていなかったのでインストール
1.1) Failure/Error: visit new_user_session_path Selenium::WebDriver::Error::UnknownError: unknown error: Chrome failed to start: exited abnormally. (unknown error: DevToolsActivePort file doesn't exist) (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) # #0 0x5595e5ed6199 <unknown> # ./spec/system/users_spec.rb:9:in `block (2 levels) in <main>' 1.2) Failure/Error: Unable to infer file and line number from backtrace Selenium::WebDriver::Error::UnknownError: unknown error: Chrome failed to start: exited abnormally. (unknown error: DevToolsActivePort file doesn't exist) (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) # #0 0x555be43fb199 <unknown>Gemfileにcapybara-webkitを追記して
bundle install
Gemfilegem 'capybara-webkit'
capybara-webkitをインストールする際にエラー
Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /home/wayne/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/capybara-webkit-1.15.1 /home/wayne/.rbenv/versions/2.7.0/bin/ruby -I /home/wayne/.rbenv/versions/2.7.0/lib/ruby/2.7.0 -r ./siteconf20210121-14230-122xkh.rb extconf.rb *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: --with-opt-dir --without-opt-dir --with-opt-include --without-opt-include=${opt-dir}/include --with-opt-lib --without-opt-lib=${opt-dir}/lib --with-make-prog --without-make-prog --srcdir=. --curdir --ruby=/home/wayne/.rbenv/versions/2.7.0/bin/$(RUBY_BASE_NAME) --with-gl-dir --without-gl-dir --with-gl-include --without-gl-include=${gl-dir}/include --with-gl-lib --without-gl-lib=${gl-dir}/lib --with-zlib-dir --without-zlib-dir --with-zlib-include --without-zlib-include=${zlib-dir}/include --with-zlib-lib --without-zlib-lib=${zlib-dir}/lib Command 'qmake ' not available
公式サイト参考にして
https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkitsudo apt-get update sudo apt-get install g++ qt5-default libqt5webkit5-dev gstreamer1.0-plugins-base gstreamer1.0-tools gstreamer1.0-x
bundle install
実行
先ほどと同じエラー
1.1) Failure/Error: visit new_user_session_path Selenium::WebDriver::Error::UnknownError: unknown error: Chrome failed to start: exited abnormally. (unknown error: DevToolsActivePort file doesn't exist) (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) # #0 0x5653be207199 <unknown> # ./spec/system/users_spec.rb:9:in `block (2 levels) in <main>' 1.2) Failure/Error: Unable to infer file and line number from backtrace Selenium::WebDriver::Error::UnknownError: unknown error: Chrome failed to start: exited abnormally. (unknown error: DevToolsActivePort file doesn't exist) (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) # #0 0x559795ddb199 <unknown>
下の記事を参考にして
Rspecの設定はrails_helper.rbにだけ書けばよいrails_helper.rb# system specでheadless chrome使う config.before(:each) do |example| if example.metadata[:type] == :system driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] end end
rspec
を実行Finished in 1.22 seconds (files took 0.7511 seconds to load) 14 examples, 0 failures通りました!
- 投稿日:2021-01-21T12:23:47+09:00
Railsチュートリアルはじめます
はじめに
2020年12月末からプログラミング学習を始め、2021年1月21日現在で以下の学習を終えました。
- HTML&CSSコース (#Progate)
- はじめてのHTML (#ドットインストール)
- はじめてのCSS (#ドットインストール)
- JavaScriptコース (#Progate)
- 詳解JavaScript 基礎文法編 (#ドットインストール)
- Rubyコース (#Progate)
- Ruby入門 (#ドットインストール)
- SQLコース (#Progate)
- MySQL入門 基礎編 (#ドットインストール)
- MySQL入門 応用編 (#ドットインストール)
- はじめてのGitとGitHub (#Udemy)
学習を通じて
今までは日々の学習をTwitterでアウトプットしていましたが、Qiitaでのアウトプットも挑戦しようと思います。
Railsチュートリアルの学習で以下のアウトプットをしていく予定です。
- できるようになったこと
- わからない→わかったまでの解決方法
- 感想や意気込み
また、Qiitaでのアウトプットを通じて、以下のスキルを伸ばしていきたいと考えています。
- マークダウン方式をできるようになる
- 140文字以上のアウトプットに慣れる
さいごに
- もっとこうしたほうがいいよ!
- ここのエラーはこういう意味だよ!
などなど…お気づきの点がございましたら、コメントいただけると大変励みになります。
どうぞよろしくお願い申し上げます。
- 投稿日:2021-01-21T11:28:40+09:00
【Rails チュートリアル】"NoMethodError (undefined method `activation_digest=' for #<User:0x00000003156938>
"NoMethodError (undefined method `activation_digest=' for #User:0x00000003156938
について
何故か本番環境だけで、このエラーがみられた
user.rb
def activate self.update_attribute(:activated, true) self.update_attribute(:activated_at, Time.zone.now) endとself.をつけ忘れてた
何故、ローカルだと問題なかったのか、、、