20200913のRubyに関する記事は15件です。

herokuでのデプロイの仕方

【概要】

1.手順

2.方法

1.手順

❶brew tap heroku/brew && brew install heroku
❷gem 'rails_12factor'
❸heroku用ファイルの作成
❹heroku用DBの作成
❺環境変数の設定
❻heroku上でmasterにpush
❼heroku上でマイグレーションの実施


2.方法

❶brew tap heroku/brew && brew install heroku

ターミナル
% brew tap heroku/brew && brew install heroku

を実行しましょう!ミスしないようにherokuに公開したいアプリの該当ファイルで行うことをお勧めします!
そして% heroku login --interactive
でherokuにログインしておきます!

❷gem 'rails_12factor'

gemfile
group :production do
  gem 'rails_12factor'
end

と記載し、% bundle installをします!
そしてmasterにコミットしておきます。

❸heroku用ファイルの作成

ターミナル
% heroku create *****

でherokuに公開したいアプリの名前を作成します。

❹heroku用DBの作成

ターミナル
% heroku addons:add cleardb

と記載しデーターベースを作成します。

ターミナル
% heroku config | grep CLEARDB_DATABASE_URL

これにより、CLEARDB_DATABASE_URLが出てくるので、使用状況によりmysql2を使用している方は、変更しましょう。

>変更方法<

ターミナル
% heroku config:set DATABASE_URL = 'mysql2:*****'

****の部分は% heroku config | grep CLEARDB_DATABASE_URLでてきたものをコピペします。

❺環境変数の設定

ターミナル
% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`

こうすることで、パスワードをファイルの中に書き込まず、見られないようにしてサイトを見るようにできます。

❻heroku上でmasterにpush

ターミナル
% git push heroku master

こちらでherokuにpushできます。

❼heroku上でマイグレーションの実施

ターミナル
% heroku run rails db:migrate

DBを❹で作っているのでそれをローカルと同じようにherokuでもマイグレーションしていきます。

これでherokuにアプリを公開できるようになります。
ただパスワードを設定していないので誰でもそのサイトを覗ける状態になっているので注意してください。
環境変数はあくまでも自分のサイトを乗っ取られないようにするためものです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】データを削除する様々な方法

早見表

メソッド 説明 削除する範囲
destroy 一件のデータを削除 対象データと関連データを削除
destroy_all 複数データを削除 対象データと関連データを削除
delete 一件のデータを削除 対象データのみ削除
delete_all 複数データを削除 対象データのみ削除

関連するデータdependent: :destroyで依存関係にあるデータのこと

使い方

# destroyメソッド
User.find(1).destroy

# destroy_allメソッド
User.where(id: 1..5).destroy_all

# deleteメソッド
User.find(1).delete

# delete_allメソッド
User.where(id: 1..5).delete_all
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[heroku] run rails db:migrateがうまくいかない

環境

・Rails 6.0.3.2
・mysql Ver 14.14 Distrib 5.6.47
・osx10.15
・herokuへデプロイ

はじめに

Railsでアプリを作成しherokuへアップロードするときにうまくいかなかった時の対応です。
開発環境ではMySQLherokuではDBがPostgreSQLのためその対応が必要。
その途中段階でエラーが生じた。
順番に書いていきます。

PostgreSQLへの対応

まずはGemfileへ以下を記述。本番環境でPostgreSQLを使うというものです。自分は一番下に書きました。

group :production do
  gem 'pg'
end

Gemfileを変更したので忘れずにbundle installをします。
まずここで一つ目のエラーでました。そのままbundle installすると自分の開発環境にはPostgreSQLがないのでエラー発生。

対応はgroup :produciton endのところを飛ばすコマンドをターミナルで実行します。

$ bundle install --without production 

データベースへ接続する記述をconfigフォルダの中にあるdatabase.ymlへします。
一番下へ追記しました。

production:
  <<: *default
  adapter: postgresql
  encoding: unicode
  pool: 5

自分の場合は記述は以上でした。
参考になった記事はコチラです!
【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39

herokuへデプロイ

今回ここは割愛します。
デプロイ完了まで進みます。

ここでdb:migrate

heroku run rails db:migrateをしますがエラー発生!
いろいろ見ているうちにこのエラーにやっと出会う。。。

ターミナルには中ほどに以下のような記述が。

Caused by:
PG::ConnectionBad: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

原因

調べてみると単純なことでherokuにはデフォルトではPostgreSQLが入ってないので、追加してあげる必要があるということです!
なんと!!!!
まだまだ慣れてないのでこの単純なことに気づけませんでした。。。。

対応

ターミナルでPostgreSQLを追加するコマンド

$ heroku addons:create heroku-postgresql

その後に

$ heroku run rails db:migrate

そうするとマイグレーションが完了しました!

別のところが誤っていると思い全然違うことをして数時間を費やしてしまいましたが、単純なことでした!
無事アプリが動作し完了しました!

参照

【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】
https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39

【Rails】「heroku run rake db:migrate」を実行しようとすると発生するエラーについて
https://qiita.com/suzuki-x/items/b878723080aea1a673ed

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ビューに画像を表示する方法

初投稿です。
至らぬ点もあるかと思いますので暖かい目で見守っていただけると幸いです・・・

Railsで画像を表示する方法にかなり手こずったのでメモとしての記録です。
それでは早速参りましょう!

※haml・scssで記述しています。

画像を表示する方法

まずは、スタンダードに画像を表示する方法。
haml・scssどちらに書いても表示されるみたいです。
どっちに書くのが正解なのと思うところです。

個人的な印象としては画像を背景として使いたい時、
例えば画像の上にテキスト情報表示したい時とか。
そんなときは、background-imageとしてscssに記述したほうが良さげ。
ここの違いよくわからないので違いがわかる方いたらご教授いただきたいです:frowning2:

まず、表示する画像がないといけません。
app/assets/images
こちらのディレクトリーに表示したい画像を格納して準備完了です。

hamlに記述する場合

ファイル名.html.haml
= image_tag ("画像名.jpg")

これじゃまだ表示できないんですよね。
widthとheightを設定してあげないと表示されません。
そんな時は、scssに画像を整える記述を書く必要があります。

_ファイル名.scss
        img {
          width: 100%;
          height: 100%;
        }

こんな感じで、width: 100%;とheight: 100%;を指定すると無事表示されます。
今回の場合は「%」ですが「px」でも可能!
hamlで書く時は”= image_tag”これが必須ですね。

scssに記述する場合

_ファイル名.scss
.クラス名 {
  height: 560px;
  width: 100%;
  background-image: image-url("ファイル名.jpg");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: top center;
}

こんな感じで書くと表示できます。
background-sizeとかその辺のプロパティ書かないと、
画像が「ばぁぁぁぁあぁぁん」ってなります。(悲惨)
あとは、widthとheightの設定も必要です。
実装したいイメージにあったプロパティを選択する必要があります。

本番環境でのみ画像が表示されない

ローカル環境で表示されるのに、本番環境で表示されない・・・
なんてこともあります。

表示できないときのコードがこちら

_ファイル名.scss
.クラス名 {
  height: 560px;
  width: 100%;
  background-image: url("ファイル名.jpg");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: top center;
}

上のコードと見比べて違うところは

_ファイル名.scss
.クラス名 {
  background-image: url("ファイル名.jpg");
}

この部分です。
この書き方だと、ローカルでは表示できるけど、本番では表示されません。

_ファイル名.scss
.クラス名 {
  background-image: image-url("ファイル名.jpg");
}

このように修正することでで本番でもローカルでも表示できるようになります。

データベースにある画像を表示する方法

例えば、商品を登録するときに画像も登録することがあります。
登録した画像を表示したい!!そんな時の方法です。

◇条件1◇画像は別テーブルで保存する場合

別テーブルで保存する理由は、複数枚画像を登録するためです。
一枚だけ登録する場合は、テーブルを分ける必要はないかと思います。

コントローラー名.rb
  def index
    @items = Item.includes(:item_images).order("created_at DESC").limit(5)
  end

こんな感じで情報を取得。
item_imagesは画像を保存している箇所です。

ファイル名.html.haml
- @items.each do |item| #eachで展開
 = image_tag item.item_images[0].image.url
_ファイル名.scss
        img {
          width: 100%;
          height: 100%;
        }

このように書くと表示できました。
正直、めっちゃ記述長い・・・そんな印象
[0]→画像は配列で格納されているみたいで何枚目かの指定をする必要があります。

◇条件2◇画像は別テーブルで保存しない場合

html.erbの記載となります。

コントローラー名.rb
  def index
    @items = Item.order("created_at DESC").page(params[:page]).per(5)
  end

こんな感じで情報を取得。

ファイル名.html.erb
<% @items.each do |item| %>
 <%= image_tag item.image.to_s, :size =>'220x220'%>

ちゃっかり、ファイル名.html.erb内でサイズ指定しちゃっています。
これで表示できました:clap:

他に、表示する方法あればご教授いただきたいです:pray:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(ギリ)20代の地方公務員がRailsチュートリアルに取り組みます【第8章】

前提

・Railsチュートリアルは第4版
・今回の学習は3周目(9章以降は2周目)
・著者はProgate一通りやったぐらいの初学者

基本方針

・読んだら分かることは端折る。
・意味がわからない用語は調べてまとめる(記事最下段・用語集)。
・理解できない内容を掘り下げる。
・演習はすべて取り組む。
・コードコピペは極力しない。

 
 第8章はログインと認証システムの開発・第3段回目、基本的なログイン機構を実装していきます。(第9章でさらに発展させていきます)
 情報技術の用語が飛び交いますので、それぞれの用語の意味・動作も理解しながら進めていきましょう。
 
本日のBGMは趣向を変えて。
TVアニメ「ゆるキャン△」オリジナル・サウンドトラック
やっと涼しくなってきました。キャンプに最適なシーズンです。コーディングで疲れた眼と頭のリフレッシュに行きましょう。

 

【8.1.1 Sessionsコントローラ 演習】

1. GET login_pathとPOST login_pathとの違いを説明できますか? 少し考えてみましょう。
→ GETはログインページのビュー取得(newアクション)、POSTはフォームに入力したデータを送信してログインを実行(createアクション)。

 
2. ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。現在、いくつのSessionsリソースがあるでしょうか? ヒント: パイプやgrepの使い方が分からない場合は Learn Enough Command Line to Be Dangerousの Section on Grep (英語) を参考にしてみてください。
→ パイプ機能:(コマンド) | (コマンド) のようにコマンド同士を繋ぐ機能。
  grepコマンド:ファイル中の文字列を検索するコマンド。
  ということで下記。signupが入ってしまうのは仕方ない?

$ rails routes | grep users#
      signup GET    /signup(.:format)         users#new
             POST   /signup(.:format)         users#create
       users GET    /users(.:format)          users#index
             POST   /users(.:format)          users#create
    new_user GET    /users/new(.:format)      users#new
   edit_user GET    /users/:id/edit(.:format) users#edit
        user GET    /users/:id(.:format)      users#show
             PATCH  /users/:id(.:format)      users#update
             PUT    /users/:id(.:format)      users#update
             DELETE /users/:id(.:format)      users#destroy
$ rails routes | grep sessions#
    login GET    /login(.:format)          sessions#new
          POST   /login(.:format)          sessions#create
   logout DELETE /logout(.:format)         sessions#destroy

 

【8.1.2 ログインフォーム 演習】

1. リスト 8.4で定義したフォームで送信すると、Sessionsコントローラのcreateアクションに到達します。Railsはこれをどうやって実現しているでしょうか? 考えてみてください。ヒント:表 8.1とリスト 8.5の1行目に注目してください。
→ routesファイルのpost '/login', to: 'sessions#create'の一文でしょう。form_forでpostリクエストを発行→ルーティングでsessionsコントローラのcreateアクションに割り当て。

 

【8.1.3 ユーザーの検索と認証 演習】

1. Railsコンソールを使って、表 8.2のそれぞれの式が合っているか確かめてみましょう. まずはuser = nilの場合を、次にuser = User.firstとした場合を確かめてみてください。ヒント: 必ず論理値オブジェクトとなるように、4.2.3で紹介した!!のテクニックを使ってみましょう。例: !!(user && user.authenticate('foobar'))
→ 下記

>> user = nil
=> nil
>> !!(user && user.authenticate("foobar"))
=> false

>> user = User.first
  User Load (0.1ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2020-09-12 09:09:50", updated_at: "2020-09-12 09:09:50", password_digest: "$2a$10$hrOEzw0faSd4yurmH8bQJOnggeNnUqTZg33yE9g7Tnk...">
>> !!(user && user.authenticate("matigatteruyo"))
=> false
>> !!(user && user.authenticate("hogehoge"))
=> true

 

【8.1.5 フラッシュのテスト 演習】

1. 8.1.4の処理の流れが正しく動いているかどうか、ブラウザで確認してみてください。特に、flashがうまく機能しているかどうか、フラッシュメッセージの表示後に違うページに移動することを忘れないでください。
→ 試してみましょう。違うページに行くとフラッシュが消えます。

 

【8.2.1 log_in メソッド 演習】

1. 有効なユーザーで実際にログインし、ブラウザからcookiesの情報を調べてみてください。このとき、sessionの値はどうなっているでしょうか? ヒント: ブラウザでcookiesを調べる方法が分からない? 今こそググってみるときです! (コラム 1.1)
 
2. 先ほどの演習課題と同様に、Expiresの値について調べてみてください。
→ まとめて下の画像。Expires = 期限切れなので、緑の四角内です。ブラウザセッション終了時が有効期限になっていますね。
スクリーンショット 2020-09-13 14.16.12.png

 

【8.2.2 現在のユーザー 演習】

1. Railsコンソールを使って、User.find_by(id: ...)で対応するユーザーが検索に引っかからなかったとき、nilを返すことを確認してみましょう。
→ 下記

>> User.find_by(id: 8)
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 8], ["LIMIT", 1]]
=> nil

 
2. 先ほどと同様に、今度は:user_idキーを持つsessionハッシュを作成してみましょう。リスト 8.17に記したステップに従って、||=演算子がうまく動くことも確認してみましょう。
→ 下記

>> session = {}
=> {}
>> session[:user_id] = nil
=> nil
>> @current_user ||= User.find_by(id: session[:user_id])
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT ?  [["LIMIT", 1]]
=> nil
>> session[:user_id] = User.first.id
  User Load (0.1ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> 1
>> @current_user ||= User.find_by(id: session[:user_id])
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2020-09-12 09:09:50", updated_at: "2020-09-12 09:09:50", password_digest: "$2a$10$hrOEzw0faSd4yurmH8bQJOnggeNnUqTZg33yE9g7Tnk...">
>> @current_user ||= User.find_by(id: session[:user_id])
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2020-09-12 09:09:50", updated_at: "2020-09-12 09:09:50", password_digest: "$2a$10$hrOEzw0faSd4yurmH8bQJOnggeNnUqTZg33yE9g7Tnk...">

 

【8.2.3 レイアウトリンクを変更する 演習】

1. ブラウザのcookieインスペクタ機能を使って (8.2.1.1)、セッション用のcookieを削除してみてください。ヘッダー部分にあるリンクは非ログイン状態のものになっているでしょうか? 確認してみましょう。
→ やってみるだけ。非ログイン状態になりました。

 
2. もう一度ログインしてみて、ヘッダーのレイアウトが変わったことを確認してみましょう。その後、ブラウザを再起動させ、再び非ログイン状態に戻ったことも確認してみてください。注意: もしブラウザの [閉じたときの状態に戻す] 機能をオンにしていると、セッション情報も復元される可能性があります。もしその機能をオンにしている場合、忘れずにオフにしておきましょう (コラム 1.1)。
→ やってみるだけー。

 

【8.2.4 レイアウトの変更をテストする メモと演習】

 ここのdigestメソッドのコードの書き方は正直??状態。:を2つ書くのってどういう意味なんでしょうか。前からちょくちょく出てきてるけど。調べると、PHPの記法は出てくるけど、同じような意味にとっていいのだろうか。
テストのアサーションなんかは用語集にまとめてます。

1. 試しにSessionヘルパーのlogged_in?メソッドから!を削除してみて、リスト 8.23が redになることを確認してみましょう。
 
2. 先ほど削除した部分 (!) を元に戻して、テストが greenに戻ることを確認してみましょう。
→ まとめて。当然失敗します。ヘッダーの表示がログイン・非ログイン時で逆になっちゃうから。戻せばGREENです。
 

【8.2.5 ユーザー登録時にログイン メモと演習】

 この章ではいろんなヘルパーメソッドを定義していますね。どこで使うために、どこに定義しているの意識しながらコードを書きましょう。コントローラで使うのか、テストで使うのか等。

1. リスト 8.25のlog_inの行をコメントアウトすると、テストスイートは red になるでしょうか? それとも green になるでしょうか? 確認してみましょう。
→ REDになります。テストにログイン状態か確かめるコード書いているので。

 
2. 現在使っているテキストエディタの機能を使って、リスト 8.25をまとめてコメントアウトできないか調べてみましょう。また、コメントアウトの前後でテストスイートを実行し、コメントアウトすると red に、コメントアウトを元に戻すと green になることを確認してみましょう。ヒント: コメントアウト後にファイルを保存することを忘れないようにしましょう。また、テキストエディタのコメントアウト機能については Test Editor Tutorial の Commenting Out (英語) などを参照してみてください。
→ (Macの場合)command+Aで全選択、command+/でコメントアウト。当然コメントアウトの前後でRED/GREENになります。

 

【8.3 ログアウト メモと演習】

1. ブラウザから [Log out] リンクをクリックし、どんな変化が起こるか確認してみましょう。また、リスト 8.31で定義した3つのステップを実行してみて、うまく動いているかどうか確認してみましょう。
→ ちゃんと動きます。

 
2. cookiesの内容を調べてみて、ログアウト後にはsessionが正常に削除されていることを確認してみましょう。
→ 削除されてます。

 

第7章まとめ

・sessionメソッドで一時的な状態保存。
・ログインではActive RecordのUserモデルを使わないので、関連づけられたエラーメッセージは使えない。
・flash.nowでrenderしたページのみフラッシュメッセージを表示。
・form_forはform_withに置き換わってるようなので参考までに。
・renderとredirect_toの使い分け。
・flashメッセージを表示。
・統合テストでログインまわりの実装を一通りテスト(ログイン/ログアウトできているか、ヘッダーは切り替わっているか)

 
 この章は大きなエラーなく進められました。次の9章から発展的な機構を導入していきます。遂に1周しかしていない章に入っていきますね!気合入れていきましょう!

 
⇦ 第7章はこちら
学習にあたっての前提・著者ステータスはこちら
 

なんとなくイメージを掴む用語集

・ステートレス・プロトコル
 状態の保持をしない独立した情報のやりとり。ログイン機能に例えると、一回ブラウザを閉じて再度入り直すと、ログインし直しになる。

・セッション(session)
 一連の通信のこと(ログインからログアウトまで等)。ェブサイトでは、初めて訪問した場合にブラウザのcookieに書き込まれる識別子のこと。

・cookie
 HTTPにおけるウェブサーバとウェブブラウザ間で状態を管理する通信プロトコル、またそこで用いられるウェブブラウザに保存された情報のこと。ECサイトの買い物カゴやログイン機能等で使われている。溜まってきたなと思ってブラウザの設定とかから消せるアレ。

・assert_redirected_to
 このアサーションの直前で呼び出されたリダイレクト先と、to以下のリダイレクト先が一致するかどうかテストする。

・follow_redirect!
 実際にそのページに移動する。移動した先で他の要素をテストする際に利用。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails チュートリアル バージョン違いで rails new できない時

超超初心者向けです。

railsチュートリアルで新しいアプリの作成時に

$ rails 6.0.3 new hello_app

を実行すると、

Traceback (most recent call last):
.
.
can't find gem railties (= 6.0.3) with executable rails (Gem::GemNotFoundException)

このようなエラーが出てしまいました。

https://teratail.com/questions/80979

↑こちらの記事を参考にさせていただいて

$ gem install rails -v 6.0.3

でgem をインストールしてもう一度

$ rails 6.0.3 new hello_app

することで解決しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ruby 例外処理

この記事について

転職活動において技術課題で例外処理を記述することがあったが、これまで経験したことがなかったのでアウトプット

例外処理とは

begin

#コードを指定してプログラム実行時に問題を検知させる
#エラーが起こりそうなコードを記述

rescue

#問題を検知した時にどのようにして対応を行わせるかを記述

end

例外を発生させる

以下のようなコードだと、100 / 0は実行できないので、answer = 100 / numberで処理が止まってしまいます。
ZeroDivisionErrorが該当のエラーであり、この例外が発生した場合に行いたい処理を記述していく。

number = 0
answer = 20 / num
puts answer
puts 2

=>`/': divided by 0 (ZeroDivisionError)
    from Main.rb:4:in `<main>'

例外処理

以下のように記述すると、本来であれば100 / 0で例外が発生するので処理が止まるところが、rescue内の処理を行うようにしているので最後まで処理が実行される。

puts 1
begin
    #検知したいコードを記述
    number = 0
    answer = 20 / num
    puts answer
rescue ZeroDivisionError => e
   #ZeroDivisionErrorが発生したら行いたい処理を記述(例外ハンドラを登録)
    p e
ensure
    puts 2
end


=>
1
#<ZeroDivisionError: divided by 0>
2

eとは何か?

発生した例外の詳細を格納してくれる、ZeroDivisionErrorのオブジェクト(変数)である。
つまりこれを出力すれば、なぜエラーが発生したのかが分かることができる。

出力の仕方

以下のようにオブジェクトはいろいろなメッセージを持っていて、必要な情報を取り出すことができる。

p e

puts e.message

p e.backtrace


=>
#<ZeroDivisionError: divided by 0>

divided by 0

["Main.rb:4:in `/'", "Main.rb:4:in `<main>'"]


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】Google API を使ったGoolgeMAPの表示とピン立て

目標

名称未設定.mov.gif

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

※ ▶◯◯ を選択すると、説明等が出てきますので、
  よくわからない場合の参考にしていただければと思います。

今回は経緯緯度をGeocodingAPIを使い取得し、MAPに表示させます。

流れ

1 gemの導入
2 .envファイルを作成 <-- 1番大事です
3 viewの編集

1 gemの導入

下記をGemfileに追加。

Gemfile
gem "dotenv-rails"
ターミナル
$ bundle install

補足
dotenv-railsは.envファイルを読み込んでくれる環境変数を管理する事が出来るgemです。

2 .envファイルを作成 <-- 1番大事です

Gemfileと同じ階層に .envファイルを作成

.env
SECRET_KEY=自分のAPIキー 
# 追加する部分に <%= ENV['SECRET_KEY'] %> と入力すると使用可能)

.gitignoreファイルの一番下に下記を追加。

.gitignore
/.env

重要
この記述を忘れてしまい、仮にGithub上に公開してしまうと、ネットに自身のAPIキーがネットに公開され、不正利用されてしまう場合があります。
もし記述し忘れで上がってしまった場合、googleに登録しているメールアドレス宛に警告メールが届くので指示に従っていただければと思います。
流れとしては、GitHubのリポジトリを削除orAPIキーの再発行(両方やるのがベストです)になるので、焦らず対処してください。

3 viewの編集

表示場所はどこでもOKです。
今回は下記ページに記載。

app/views/homes/mypage.html.erb
<h2>Your MAP</h2>
<div id='map' class="<%= current_user.prefecture_code + current_user.city + current_user.street %>"></div>

<style>
#map{
  height: 300px;
}
</style>

<script>

let map
let geocoder

function initMap(){
  geocoder = new google.maps.Geocoder()
  geocoder.geocode( { 'address': $('#map').attr('class')}, function(results, status) {
    if (status == 'OK') {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
          map: map,
          position: results[0].geometry.location
      });
    } else {
      alert('Geocode was not successful for the following reason: ' + status);
    }
  });

  map = new google.maps.Map(document.getElementById('map'), {
  center: {lat: -35.6809591, lng: 139.7673068},
  zoom: 13
  });
}

function codeAddress(){
  let inputAddress = document.getElementById('address').value;
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['SECRET_KEY'] %>&callback=initMap" async defer></script>

下記は補足を加えたコードになります。

app/views/homes/mypage.html.erb
<h2>Your MAP</h2>
<!-- id=mapのclassに登録住所を代入。 -->
<div id='map' class="<%= current_user.prefecture_code + current_user.city + current_user.street %>"></div>

<!-- id=mapの大きさを指定。※stylesheetにまとめてもOK -->
<style>
#map{
  height: 300px;
}
</style>

<script>
// 下記codeAddressでも使うため、mapを関数の外で定義、geocoderも用意
let map
let geocoder

function initMap(){
  // geocoderを初期化
  geocoder = new google.maps.Geocoder()
  // geocoderのgeocode()methodで、経緯緯度をGeocoderAPIにリクエストを送信。
  // geocode()methodでaddressにid=mapのclassの登録住所を代入し、経緯緯度を取得。
  geocoder.geocode( { 'address': $('#map').attr('class')}, function(results, status) {
    // もしエラーがなければ、
    if (status == 'OK') {
    // map.setCenterで上記記述の経緯緯度に地図が移動。
      map.setCenter(results[0].geometry.location);

    // google.maps.MarkerでGoogleMap上の指定位置にマーカが立つ
      var marker = new google.maps.Marker({
          map: map,
          position: results[0].geometry.location
      });
    // エラーが出た場合には
    } else {
    // statusにエラー状況が表示されるので、その文言を調べれば解決できます。
      alert('Geocode was not successful for the following reason: ' + status);
    }
  });

  // mapの初期位置を指定。
  // latは経緯、lngは緯度。(下記は東京駅を指定しています)
  map = new google.maps.Map(document.getElementById('map'), {
  center: {lat: -35.6809591, lng: 139.7673068},
  // お好みでズームサイズを変更できます。
  // 数字が大きければ、拡大です。
  zoom: 13
  });
}

function codeAddress(){
  // 入力を取得
  let inputAddress = document.getElementById('address').value;
  // geocodingしたあとmapを移動
}
</script>
<!-- GoogleAPIキーを読み込むための記述になります。 -->
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['SECRET_KEY'] %>&callback=initMap" async defer></script>

補足【うまくいかない時】
住所の登録ができているものの、ピン立てされていない時、
Geocoding Service
これを参考にGeocoding APIを有効化すればOK。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】content_tagを解説してみる。

忘備録的に書いていきます。間違っている点などありましたら、コメントしていただけるとありがたいです?‍♂️

 【概要】content_tagとは

  • Railsのview helperで使われる。
  • HTMLコードの要素を生成することができる。

 【何が嬉しいのか?】

HTMLコードを直に書くとセキュリティ面で脆弱性が出てしまうことがある。(XSS,CSRFであったり。)

上記のようなことを防ぐために、Railsに乗っていく(content_tagを使う)とセキュリテイ面で恩恵を受けることができます。

HTMLerbがごちゃごちゃになってしまう場合に整理して書けるというメリットもあります。

小さくパーシャル化するのにも使えるかもしれませんね。

 【基本的な使い方】

content_tag :p, 'Hello, World!' # => <p>Hello, World!</p>

第一引数にタグを指定し、第二引数にcontentとなる部分を埋め込む。

ちなみに、第二引数にはシンボル(:pみたいな)だけではなく、文字列も許容してくれる

content_tag 'p', 'Hello, World!' # => <p>Hello, World!</p>

少し、実践的な書き方をするとこんな感じ???

content_tag :p, @user.name # => <p>佐藤</p>

 「こんなこともできるよ」集

 HTMLオプションはハッシュで

content_tag :p 'Hello' class: 'hoge' # => <p class='hoge'>Hello</p>

こんな感じでclassを持たせることもできます。ちなみに、複数のclassを持たせるには下記のように書けばOK

content_tag(:p, 'Hello', class: ["hoge", "foo"])
# => <div class="hoge foo">Hello</div>

 ネストもできるよ

content_tag :div do
  content_tag :p @user.name
  content_tag :p @user.age
end

こんな感じにネストして書くこともできる。

 おいおい、#tagって知ってるか??

下記はみんな大好きDHHのissueです。

https://github.com/rails/rails/issues/25195 

content_tag :span, nil, class: 'bookmark'
# 下記は上記と同じ意味
tag.span class: 'bookmark'

すごい直感的に書けるようになりましたよね。

色々変わったのですが、個人的には下記がお気に入り。

tag.div(id: 'header') { |tag| tag.span 'hello' }
# <div id="header"><span>hello</span></div>

でも、下記も簡潔に書けますよね。

<%= tag.p do %>
 hoge
<% end %>

特に理由がなれば、content_tagではなく、tagを使うと可読性が上がるかな〜と思いました。

 参考関連記事

https://qiita.com/ren0826jam/items/0ebd451d1da90e496c2f
https://makicamel.hatenablog.com/entry/2019/03/07/224552
https://techracho.bpsinc.jp/hachi8833/2018_11_01/48191

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 6で認証認可入り掲示板APIを構築する #8 seed実装

Rails 6で認証認可入り掲示板APIを構築する #7 update, destroy実装

seedとは

開発中にテストデータが必要な時、都度rails cやらcreate actionを叩いてレコード作るのは手間です。
そこで、コマンドを叩くだけであらかじめ設定しておいたレコードを、50だろうが1000だろうが簡単に作れるseedを取り入れます。

ファイル作成とロード

rails seedだけでググると大抵db/seeds.rbに直書きばかり出てきますが、modelが多くなると管理がしづらくなります。
そこでファイルを分割し、db/seeds.rbからrequireで呼ぶ形式にします。

こうすることで追加削除時の管理がしやすくなりますし、seedはファイル指定で実行することもできるので便利です。

$ mkdir db/seeds
$ touch db/seeds/post_seeds.rb
db/seeds.rb
# frozen_string_literal: true

seed_models = %i[post]
seed_models.each do |model|
  require "./db/seeds/#{model}_seeds"
end
db/seeds/post_seeds.rb
# frozen_string_literal: true

unless Post.exists?
  20.times do
    Post.create!(subject: "hoge", body: "fuga")
  end
end

今後seed対象のmodelが増えることを予想し、seed_modelsという変数に追加していくことで外部ファイル読み込みをするようにします。
ディレクトリ走査することで都度db/seeds.rbを変更しなくても良い作りにできるのですが、postモデルの前に今後作るuserモデルのレコードが存在していないといけない等の依存関係が発生するので、手動で実行順を弄れるように書いています。

post_seeds.rbの中身は単純にPost.create!を20回実行しているだけです。
!を付けることによりバリデーションエラーで登録できなかった際に例外が投げられるので、気付いたらレコードが生成されていなかった事態を防げます。

$ rails db:reset
$ rails db:seed
$ rails c
[1] pry(main)> Post.count
   (1.1ms)  SELECT COUNT(*) FROM "posts"
=> 20

db:resetすることでテーブルを全dropし再生成。これでレコードがある時のみ動くseedが実行されます。
そしてdb:seedすることで、20レコードが追加されていることが確認できます。

Fakerの導入

レコードができたのはいいのですが全部subjectがhoge, bodyがfugaになっています。
このままだと、何かしらの原因でAPIから取得したら同一レコードが紛れていたりしても気付きづらくなります。
とはいえ完全ランダムな文字列を都度作るのも手間だし…ということで、役立つのがFakerです。

とりあえず入れてみましょう。

Gemfile
...
group :development, :test do
...

+   "faker"
end
...
$ bundle

試しに使ってみましょう。

$ rails c
[1] pry(main)> Faker::Name.unique.name
=> "Miss Porter Kovacek"
[2] pry(main)> Faker::Name.name
=> "Felicita Durgan"
[3] pry(main)> Faker::Name.name
=> "Yong Weissnat"
[4] pry(main)> Faker::Name.name
=> "Sandie Oberbrunner"

こんな感じに、実行のたびにランダムな名詞や文章を自動で返してくれるものです。
デフォルトで定義されている語句はGithubで確認すると良いです。
人名や動物、住所や電話番号等だけでなく、映画、漫画、ゲーム、ドラマ、音楽なんかもあります。ポケモン名とかONE PIECEの悪魔の実とかまでありますね。

seedsにFakerを入れる

db/seeds/post_seeds.rb
# frozen_string_literal: true

unless Post.exists?
  20.times do
-    Post.create!(subject: "hoge", body: "fuga")
+    Post.create!(subject: Faker::Lorem.word, body: Faker::Lorem.paragraph)
  end
end
$ db:reset
$ db:seed
$ rails c
[1] pry(main)> Post.all
  Post Load (0.4ms)  SELECT "posts".* FROM "posts"
=> [#<Post:0x000000000636cbe8
  id: 1,
  subject: "quos",
  body: "Earum numquam qui. Impedit autem molestias. Ipsum adipisci eos.",
  created_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00,
  updated_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00>,
 #<Post:0x00000000063b5be0
  id: 2,
  subject: "vero",
  body:
   "Impedit distinctio saepe. Adipisci cupiditate officiis. Vel et deleniti.",
  created_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00,
  updated_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00>,

ランダムなsubject, bodyのレコードができていることが確認できます。

Fakerを日本語化する

せっかく入れたのに英語だと日本語サイトを作る上で不便なので、ローカライズしましょう。
db:seedはdev環境で実行するので、dev環境の時にFakerを日本語化してみます。

config/environments/development.rb
 Rails.application.configure do
...

+  Faker::Config.locale = "ja"
 end

常に日本語化が嫌なのであれば、Faker::Config.locale = "ja"をdb/seeds/post_seeds.rbに入れてもOKです。
その後再度seedを実行します。

$ rails db:reset
$ rails db:seed
$ rails c
[1] pry(main)> Post.all
  Post Load (0.3ms)  SELECT "posts".* FROM "posts"
=> [#<Post:0x0000000006480b88
  id: 1,
  subject: "いく",
  body: "警官総括大尉。めいしぼきんかたみち。伝統徳川超〜。",
  created_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00,
  updated_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00>,
 #<Post:0x00000000064fb928
  id: 2,
  subject: "フランス語",
  body: "〜系けいかん先週。うえる自宅そだてる。店舗にんい高値。",
  created_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00,
  updated_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00>,

無事に日本語化されていますね。
なお、日本語化されているものはGithubで確認できます。逆に言えばこの中に無いものは英語のままです。

続き

Rails 6で認証認可入り掲示板APIを構築する #9 serializer導入
連載目次へ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails uninitialized constant エラーの解決へのシンプルなチェックリスト

これはなにか

Railsをそれなりにやっているにも関わらず、uninitialized constant error にハマってしまったのでチェックリストをここにまとめておこうと思う。

結論

チェックするべき項目は以下3点である。

  1. ファイル名とclass名が一致しているか?
  2. ファイルpathとmoduleの定義が一致しているか?
  3. Railsにファイルを読み込ませているか?

以下詳細をかいていく。

ファイル名とclass名が一致しているか?

以下のようなclassが存在していたら、ファイル名はqiita_user.rb でないといけない。

class QiitaUser
  def hoge
  end
end

ファイルpathとmoduleの定義が一致しているか?

以下のようなmoduleにnestされたclassが存在していたら、pathは **/v1/auth/user.rb のようになるだろう。

class V1::Auth::User
end

OR

module V1
  module Auth
    class User
    end
  end
end

Railsにファイルを読み込ませているか?

Railsのデフォルトのフォルダ以外に、フォルダを追加する場合、autoload pathに追加したフォルダへのpathを定義する必要がある。
app/lib/hoge/foo.rb を追加したとする。この場合、config/application.rb に以下の様な形で、autoload pathを追加する必要がある。

module App
  class Application < Rails::Application
    # 省略

    config.autoload_paths += Dir.glob("#{config.root}/app/lib")
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

slimの長い構文を途中で改行する

Railsアプリ開発時にslimを使ってhtmlを書いているときに、このような長い構文がある。これを改行する方法。

.card-toolbar
  a.btn.btn-primary.status-editable data-confirm="全ユーザーの編集権限を「編集可」に変更します。よろしいですか?" style="font-size: 15px; margin: 0 10px;" href="#{toggle_status_editable_admins_supplier_company_path(supplier_company_code: model.code, supplier_company_id: model.id)}" role="button" 編集可
  a.btn.btn-danger.status-editable data-confirm="全ユーザーの編集権限を「編集可」に変更します。よろしいですか?" style="font-size: 15px; margin: 0 10px;" href="#{toggle_status_not_editable_admins_supplier_company_path(supplier_company_code: model.code, supplier_company_id: model.id)}" role="button" 編集不可

こんな感じで[]をつけて改行できる。

.card-toolbar
  a[data-confirm="全ユーザーの編集権限を「編集可」に変更します。よろしいですか?" 
    style="font-size: 15px; margin: 0 10px;" 
    href="#{toggle_status_editable_admins_supplier_company_path(supplier_company_code: model.code, supplier_company_id: model.id)}" 
    role="button"]
    .btn.btn-primary.status-editable
     | 編集可
  a[data-confirm="全ユーザーの編集権限を「編集不可」に変更します。よろしいですか?" 
    style="font-size: 15px; margin: 0 10px;" 
    href="#{toggle_status_not_editable_admins_supplier_company_path(supplier_company_code: model.code, supplier_company_id: model.id)}" 
    role="button"]
    .btn.btn-danger.status-editable 
     | 編集不可
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]外部キー制限かかっているときにdestoryできないエラーを発生させたい時の対処

はじめに

レコード削除時に関連づけられたレコードが存在するときに、例外やエラーを発生させたい。
外部キーで使用されていると親要素が消されては困るというシチュエーションです。

削除しようとするとRubyのエラー画面が出てしまう。

原因

Modelに関係づけされたモデルに対する挙動を定義するが無いからでした。
マイグレーションファイルのforeign key: Trueだけでは不十分でした。

対策

Modeldependentオプションを記述することで解決しました。
該当のモデルに以下の記述をします。

#contractというモデル
class Contract < ApplicationRecord
  has_many :...., dependent: :restrict_with_error

end

アソシエーション記述の後にdependent: :restrict_with_errorと記述することでdestoryできないときのエラーを表示することができた。
以下の条件分が成り立ち解決しました!。

#contractというモデルのコントローラー
def destroy
    contract = Contract.find(params[:id])
    if contract.destroy
      redirect_to contract_path, notice: "選んだ契約を削除しました"
    else
      redirect_to contract_path, alert: "使用中のため削除できません"
    end
end

参照

https://dorarep.page/articles/rails-dependent#dependent_restrict_with_exception_restrict_with_error

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]errorsメソッドでメッセージ表示させるとビューが崩れる時の対処

はじめに

formで入力に誤り(例えば無入力)があるとエラーメッセージを表示させるためにerrorsメソッドを用いて記述し、動きを確認するとビューが崩れるという問題が発生しました。その時の自分の解決した方法です。

原因

崩れたビューを確認するとfield_with_errorsというdivクラスが付与させていていることを確認した。これが原因である。

対処

今回はこのfield_with_errorsというdivクラスが付与されないようにした。

config/application.rbに以下の記述をした。

module #モデル名
  class Application < Rails::Application

    config.load_defaults 6.0
    config.i18n.default_locale = :ja

    config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }
    #↑この記述をプラスした

  end
end

こうすることで余計なクラスが付与されずにできました!

参考

https://yukimasablog.com/rails-field-with-errors

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]errorsメソッドでエラーメッセージが出せないときの対処

はじめに

例えばresult.saveのように変数resultの保存をしようとした時に、失敗するとresultにエラーメッセージが格納される。
これを利用してエラーメッセージを表示させたいがRubyのエラー画面となる。

言い換えると思い通りのエラーメッセージが出ない。

エラー時にコンソールで確認の以下のようになる

result.errors.any? => False

保存できてないのにエラー出てないことになってる。

今回は無入力で登録しようとするとエラーを出したい。

原因

Modelにバリデーション記述が無かったことが原因。
テーブル作成時にはカラムに制限(無入力制限のため null: falseとした)がそれだけではエラーメッセージがでない。

対策

Modelに以下のような記述をした。

class Result < ApplicationRecord
  belongs_to ...
  has_many ...
  validates :name, presence: true

  ...
end

validates :name, presence: trueと記述することで

result.errors.any? => True

となり

result.errors.full_messages

で、エラーメッセージ全件の内容を取得しeachを用いて取り出せました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む