- 投稿日:2019-08-28T23:07:31+09:00
Railsでメール送信機能を実装する手順を結構丁寧に(development環境編)
次からもっとスムースにできるように、ここに執筆します。
前提
- バージョンは
Rails 5.2.3です。- テンプレートエンジンはHamlを使っていますが、ERBでもSlimでもそんなに変わらないはずです。
$ rails -v Rails 5.2.3要件(仕様、やりたいこと)
- 問い合わせフォームで必要事項を入力して送信すると、その内容をDBに保存するとともに、管理者にテキストメールで通知する。
letter_opener を導入する
- letter_opener というgemを導入すると、開発中にテストで送信したメールが実際にアドレス先に飛んでいく代わりに、ブラウザのポップアップで確認できるようになります。
- 導入することで、テスト用のメールが誤って実際に使われているアドレス先に送信されるのを防ぐことができます。
- 実際にやってみればどうなるかわかると思いますので、とりあえず以下の手順で導入だけ済ませておきます。
Gemfilegroup :development do gem 'letter_opener' end$ bundle installconfig/environments/development.rbconfig.action_mailer.delivery_method = :letter_opener実装
では実装していきます。
config/environments/development.rbを編集する
config.action_mailer.raise_delivery_errors = falseをコメントアウトすることで、development環境からもメールを送信する設定に切り替えることができます。config.action_mailer.delivery_methodは先ほど追加した部分です。config.action_mailer.default_url_optionsは、後述のメールテンプレート内でURLヘルパーを使用できるようにする設定です。config/environments/development.rbRails.application.configure do #...(中略)... # コメントアウトすることでdevelopment環境からもメールを送信する設定になる # config.action_mailer.raise_delivery_errors = false # smtpで実際にメール送信させるのではなく、letter_openerというgemを用いてテストする # config.action_mailer.delivery_method = :smtp config.action_mailer.delivery_method = :letter_opener # メールテンプレートはviewと違ってURLヘルパーを使ってもドメインが取得できず、メール本文にURLを載せられないので、その対策をする config.action_mailer.default_url_options = {:host => 'localhost:3000'} endメーラークラスを作成する
rails generateコマンドが使用できます。- 今回はHTMLメールではなくテキストメールを実装したいため、
app/views/notice_mailer/sendmail_contact.html.hamlは削除します(HTMLテンプレートの方が優先して呼ばれるみたいなので、そちらを残しておくとエラーになったり意図しない内容のメールになってしまいます)。$ rails g mailer Notice sendmail_contact Running via Spring preloader in process 1180 create app/mailers/notice_mailer.rb invoke haml create app/views/notice_mailer create app/views/layouts/mailer.text.haml create app/views/layouts/mailer.html.haml create app/views/notice_mailer/sendmail_contact.text.haml create app/views/notice_mailer/sendmail_contact.html.haml ->削除する
- メーラークラスは以下の内容にします。
app/mailers/notice_mailer.rbclass NoticeMailer < ApplicationMailer # メール送信元アドレスを設定する default from: "noreply@example.com" def sendmail_contact(contact) @contact = contact # メール送信先アドレスを設定する mail to: "admin@example.com", subject: "お問い合わせが届きました" # メール件名 end endメールテンプレートを作成する
- ここに記述した内容がメール本文になります。
- メーラークラスのメソッド内で使用したインスタンス変数は、ここで参照できます。
- バックスラッシュを使うことで、改行できます。
- 先述した通り、
config/environments/development.rbに必要な設定をしていれば、URLヘルパーを使うこともできます。app/views/notice_mailer/sendmail_contact.text.hamlお問い合わせが届きました。 \ = "会社名: #{@contact.company}" = "お名前: #{@contact.name}" = "メールアドレス: #{@contact.email}" = "電話番号: #{@contact.telephone}" = "お問い合わせ内容:" = @contact.messageメーラークラスのメソッドを呼び出す
- 追加しているのは、
NoticeMailer.sendmail_contact(@contact).deliverの1行です。app/controllers/contacts_controller.rbclass ContactsController < ApplicationController def new @contact = Contact.new end def create @contact = Contact.new(contact_params) if @contact.save NoticeMailer.sendmail_contact(@contact).deliver # ここで呼び出している redirect_to new_contact_url, notice: '問い合わせの送信に成功しました。' else render :new end end private def contact_params params.require(:contact).permit(:company, :name, :email, :telephone, :message) end endこれで一通りの実装が完了しました。実際に動かしてみましょう!
(option)development環境から実際にメール送信する
- letter_opener を使わず、実際にメールを送信してみる場合は、
config/environments/development.rbを以下のように記述します。- 今回は、ドメインはGmailのものを設定します。
- Gmailのアプリパスワードというのは、普段Googleのアカウントにログインするために使っているパスワードとは異なりますので、ご注意ください。
config/environments/development.rbRails.application.configure do #...(中略)... # コメントアウトすることでdevelop環境からもメールを送信する設定になる # config.action_mailer.raise_delivery_errors = false # smtpで実際にメール送信させる config.action_mailer.delivery_method = :smtp # config.action_mailer.delivery_method = :letter_opener # メールテンプレートはviewと違ってURLヘルパーを使ってもドメインが取得できず、メール本文にURLを載せられないので、その対策をする config.action_mailer.default_url_options = {:host => 'localhost:3000'} config.action_mailer.smtp_settings = { :enable_starttls_auto => true, :address => 'smtp.gmail.com', :port => 587, :domain => 'gmail.com', :authentication => :plain, # 本当に飛ばす場合(letter_openerを使わない場合)は、Gmailのメールアドレスが必要 :user_name => 'aaaaa@gmail.com', # 本当に飛ばす場合(letter_openerを使わない場合)は、Gmailのアプリパスワードが必要 :password => 'aaaabbbbccccdddd' } end(WIP)production環境から実際にメール送信する
- 本番環境については別記事にまとめる予定です。まだ私も実装できていないので…。
参考
- 投稿日:2019-08-28T22:41:50+09:00
Railsチュートリアル(第12章)
はじめに
Railsチュートリアルの第12章が終わりました。
この章では、パスワード再設定を行います。
メールを送って再設定用のリンクにアクセスする基本的な流れは11章と同じです。
ポイントだけメモしておきます。隠しフィールド
メールアドレスからユーザーを特定するために、メールで送信したリンクからアクセスした際のeditアクションと、その後のパスワード再設定フォームからの送信時のupdateアクションでそれぞれメールアドレスが必要です。
リンクからアクセスする際は、リンクのパラメータにメールアドレスを含めていますが、フォームの送信で消えてしまいます。そのために、フォーム内に隠しフィールドとして保持します。以下のように、
hidden_field_tagで記述します。<%= form_for(@user, url: password_reset_path(params[:id])) do |f| %> ... <%= hidden_field_tag :email, @user.email %> ... <% end %>
f.hidden_fieldを使用しないのは、以下のようにパラメータの取得の仕方が変わるからです。hidden_field_tag :email, @user.email # params[:email] f.hidden_field :email, @user.email # params[:user][:email]時間の比較
時間も数値等と同じように比較することができます。
以下のように記述することで、reset_sent_atが2時間より前かどうか判定しています。reset_sent_at < 2.hours.ago考え方としては、
reset_sent_atが2.hour.ago(2時間前の時間)より前であればtrueです。
- 投稿日:2019-08-28T22:28:31+09:00
Rails & Nuxt.jsのアプリケーションにGraphQLを導入する
前提
Rails & Nuxt.jsのDocker環境をalpineイメージで構築する
こちらのポストの環境をもとに進めるので、Dockerのサービス名等は適宜読み替えていただくようにお願いします。ディレクトリ構成
後述のコマンドでは、Railsはbackend、NuxtはfrontendがDockerのサービス名になっています。. ├── backend <- Ruby on Rails │ ├── Dockerfile │ ├── Gemfile │ ├── Gemfile.lock │ (中略) │ ├── frontend <- Nuxt.js │ ├── Dockerfile │ ├── README.md │ ├── nuxt.config.js │ ├── package-lock.json │ ├── package.json │ (中略) │ ├── docker-compose.yml └── .envライブラリ追加
Rails
- graphql-ruby ... RubyでGraphQLを導入するならコレ
- graphiql-rails ... GraphQL IDE のRails版。ブラウザから
./backend/Gemfileを修正し、bundle installします。## (中略) ## gem 'graphql' #added group :development do gem 'listen', '>= 3.0.5', '< 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' gem 'graphiql-rails' #added end ## (中略) ##$ docker-compose exec backend bundle installNuxt
こちらのライブラリをインストールします。
本記事では graphql-tag は使いません。$ docker-compose exec frontend yarn add @nuxtjs/apollo実装
Rails
generator で雛形を作成します。
$ docker-compose exec backend rails g graphql:installgraphiql-railsの Readme にしたがって、Railsのconfigファイルを修正します。
./backend/config/routes.rbGraphiQLエンジンをマウントし、ブラウザからアクセスできるようにします。
Rails.application.routes.draw do post "/graphql", to: "graphql#execute" #generatorでinsertされる # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html #added if Rails.env.development? mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: '/graphql' end end
./backend/config/application.rbAPIモードの場合に必要な修正です。
## (中略) ## - # require "sprockets/railtie" + require "sprockets/railtie" ## (中略) ##GraphiQLで動作確認
dockerコンテナを再起動後、ブラウザで http://localhost:3000/graphiql にアクセスし、GraphiQLを開きます。
./backend/app/graphql/types/query_type.rbのサンプルを利用して、下記のようにqueryの結果が返ってくればOKです。$ docker-compose restart backendNuxt
Nuxtアプリのルートに、下記のディレクトリ、ファイルを追加、編集します。
今回はmutationは使いませんが、あわせて作成しておきます。. └── frontend ├── nuxt.config.js │ ├── pages │ └── index.vue │ └── apollo ├── client-configs │ └── default.js └── gqls ├── mutations └── queries └── getTestField.gql
./frontend/nuxt.config.jsNuxtでapolloクライアントを使用するための設定を追加します。
default.jsを読み込まず、nuxt.config.jsに直書きしてもOKです。export default { /* (中略) */ modules: [ '@nuxtjs/apollo', //added ], /* (中略) */ apollo: { clientConfigs: { default: '~/apollo/client-configs/default.js' } } }
./frontend/apollo/client-configs/default.jsapolloには様々なオプションありますがが、今回はqueryの実行が確認できればよいので最低限です。
uriのホスト名は、DockerのRailsアプリのサービス名backendになります。import { HttpLink } from 'apollo-link-http' export default () => { const httpLink = new HttpLink({ uri: 'http://backend:3000/graphql' }) return { link: httpLink } }
./frontend/apollo/gqls/queries/testField.gqlGraphiQLで実行したものです。
query { testField }
./frontend/pages/index.vuequeryを実行した結果を表示します。
<template> <p>{{ testField }}</p> </template> <script> import testField from '~/apollo/gqls/queries/testField'; export default { data() { return { testField: {} } }, apollo: { testField: { query: testField } } } </script>お疲れさまでした。
(簡略化シすぎた感)
- 投稿日:2019-08-28T20:53:07+09:00
【Rails】dotenvで管理していた環境変数が反映されなくなった時やってみること
dotenvで管理していた環境変数が反映されなくなって大変こまった
環境変数をカンタンに管理できる便利gem、dotenvを利用していましたがプルリクやマージやら重ねてるうちに環境変数が反映されなくなってしまいました...。
この記事を必要としていた人に教えられること
ない、結論から言うとbundle updateしたら直った。原因わからないから教えて欲しい。
私が使っていた環境とか
$ rails -v Rails 5.2.3 dotenv 2.7.5 dotenv-rails 2.7.5ちなみに次のようにGemfileに書き込み、dotenvを利用しています。
Gemfilegem 'dotenv-rails'.envはルートディレクトリに置いてあった
参考
spring stopしたらいいらしいです、私はやってませんが...
https://qiita.com/metafalse/items/7294afa3d1be3315e999
- 投稿日:2019-08-28T20:40:16+09:00
Railsチュートリアルメモ 第3章
個人的なメモ。
Railsチュートリアルでは2章ではScaffoldを使ってあらましを、
3章から本格的にアプリ制作に入る。
3章では「静的なページの制作」、「自動テストのあらまし」の学習をするメモでは気になった部分、忘れそうな部分を記述。
3章 ほぼ静的なページの作成
3.2 静的ページ
3.2.1 静的なページの生成
コントローラ生成(rails generate)時にアクションは複数指定できる
$ rails generate controller StaticPages home helphome helpのようにcontroller名のあとに複数指定可能
Rubyの命名規則の特徴
クラス名にはキャメルケース(例:StaticPages)が使われる
ファイル名にはスネークケース(例:static_pages)が使われる
※あくまで慣習だが、同様に習うべきRailsコマンドの短縮
完全なコマンド 短縮形 $ rails server$ rails s$ rails console$ rails c$ rails generate$ rails g$ rails test$ rails t$ bundle install$ bundleRailsでの手戻し
コントローラ, モデル
$ rails destroy controller HogeHoges
generateに対してのdestroy※ destroy時、
/config/routes.rb内にルーティングが残っているかもしれない。手作業で削除DB
DBも逐一マイグレーションが必要
$ rails db:migrateだが、1手手戻しもできる
$ rails db:rollbackまたdbのマイグレーションは逐一バージョンが付与されているので、最初に戻す場合、以下
$ rails db:migrate VERSION=03.2.2 静的なページの調整
viewsの場所
app/views/コントローラ名/アクション名.html.erb
erb (Embedded Ruby)
htmlにrubyを埋め込んである。3.3 テストから始める
テスト駆動開発 (test-driven development; TDD)
RailsチュートリアルではガチガチのTDDでは進みが悪いので、必要に応じてTDDチュートリアル内で行うテストは3つ
- コントローラテスト (3章〜)
- モデルテスト (6章〜)
- 統合テスト (7章〜)
3.3.1
コントローラテスト
$ rails generate controller hogehogeの時点でテストが既に作成されている。
/test/controllers/3.3.2
テスト駆動のサイクル
- 失敗するテストを最初に書く
- アプリケーションのコードを書いて成功させる (パスさせる)
- 必要ならリファクタリングする
それぞれステータスから
- RED
- GREEN
- REFACTOR
とも。
このサイクルを繰り返す。以下テストを元に、
$ rails testを確認しながら、通るようにしていく。
テストを書き、通るように開発。簡単なTDD。require 'test_helper' class StaticPagesControllerTest < ActionDispatch::IntegrationTest # 省略 test "should get about" do get static_pages_about_url assert_response :success end endリファクタリング
「1匹いたら30匹いると思え」
金言。BUGでなくとも腐敗臭漂うだけでリファクタリングもの。
ネズミもGもBUGもスパゲッティコードも。早いうちからのリファクタリングが大事。3.4 少しだけ動的なページ
HTML内でheadのtitleタグを動的に表示し、TDDでつなぐ。
3.4.2
リファクタリング。
2,3回出てくる文字列を変数化
(インスタンス変数、文字列の式展開について、触れられている)3.4.3
DRY (Donot Repeat Yourself)
Rubyの原則。
共通部分をRailsの機能でまとめる。
/app/views/layouts/application.html.erb
上記に大枠のレイアウトを記述。
その他アクションのerb内の内容は、application.html.erb内に
<%= yield %>
と記述し、挿入する。3.5 最後に
コミットとデプロイ
masterブランチに変更をmerge
herokuにデプロイ$ git checkout master $ git merge 作業ブランチ名 # プッシュとデプロイ $ git push # github側 push $ rails t # herokuデプロイ前テスト $ git push heroku # heroku側 push $ heroku open # 確認デプロイ前に
rails testを実行。癖をつけるようにする。3.6 高度なセットアップ
3.6.1 minitest reporters
minitest-reporters (gem) でRailsのテストを見やすくする。
RED、GREENで色がつくようになる。3.6.2 Guardによるテストの自動化
Guardというgemでファイルを監視、自動テスト
$ bundle exec guard init # 初期化 $ bundle exec guard # 監視スタートguardのプロンプトが開く。
フルスキャンはそのままEnter。
終了は<C-d>でデタッチ。GuardはSpringサーバ(Railsの機能)を使うが、バグが有りプロセスが残ることが有るので、重いときには余計なものをkillする。
Linux killコマンド
プロセスのkill
$ ps aux | grep springパイプでgrepに渡し、springのみ抽出
pid(数字5桁)を指定してkill$ kill -15 12345 #pidはあくまで例ここのoptionで指定するシグナルは15がterminationで一緒か?
どうやらCPUごとに一部変わるそうで、x86なら-15でSIGTERM(termination)で終了できるらしい。
我が家のintelmacさんはx86かと思うので-15Springなら
1. 一括終了を最初に試す、
2. ダメならpkill$ spring stop $ pkill -15 -f プロセス名 # ダメなら所感
テスト駆動で書きながら、コントローラからビューに至るまでの流れをトレースできたように思う。
簡単なテストだが、まだ苦に思わない程度で済んでいる。
演習で2,3度同じような作業が繰り返されるので、少しずつ馴染めそう。
- 投稿日:2019-08-28T20:40:16+09:00
Railsチュートリアル(第4版)メモ 第3章
Railsチュートリアル(第4版)の個人メモ
気になった部分、忘れそうな部分を記述。
- Ruby 2.6.1
- Rails 5.1.6
2章ではScaffoldを使ってあらましを、
3章から本格的にアプリ制作に入る。
3章では「静的なページの制作」、「自動テストのあらまし」の学習をする3章 ほぼ静的なページの作成
3.2 静的ページ
3.2.1 静的なページの生成
コントローラ生成(rails generate)時にアクションは複数指定できる
$ rails generate controller StaticPages home helphome helpのようにcontroller名のあとに複数指定可能
Rubyの命名規則の特徴
クラス名にはキャメルケース(例:StaticPages)が使われる
ファイル名にはスネークケース(例:static_pages)が使われる
※あくまで慣習だが、同様に習うべきRailsコマンドの短縮
完全なコマンド 短縮形 $ rails server$ rails s$ rails console$ rails c$ rails generate$ rails g$ rails test$ rails t$ bundle install$ bundleRailsでの手戻し
コントローラ, モデル
$ rails destroy controller HogeHoges
generateに対してのdestroy※ destroy時、
/config/routes.rb内にルーティングが残っているかもしれない。手作業で削除DB
DBも逐一マイグレーションが必要
$ rails db:migrateだが、1手手戻しもできる
$ rails db:rollbackまたdbのマイグレーションは逐一バージョンが付与されているので、最初に戻す場合、以下
$ rails db:migrate VERSION=03.2.2 静的なページの調整
viewsの場所
app/views/コントローラ名/アクション名.html.erb
erb (Embedded Ruby)
htmlにrubyを埋め込んである。3.3 テストから始める
テスト駆動開発 (test-driven development; TDD)
RailsチュートリアルではガチガチのTDDでは進みが悪いので、必要に応じてTDDチュートリアル内で行うテストは3つ
- コントローラテスト (3章〜)
- モデルテスト (6章〜)
- 統合テスト (7章〜)
3.3.1
コントローラテスト
$ rails generate controller hogehogeの時点でテストが既に作成されている。
/test/controllers/3.3.2
テスト駆動のサイクル
- 失敗するテストを最初に書く
- アプリケーションのコードを書いて成功させる (パスさせる)
- 必要ならリファクタリングする
それぞれステータスから
- RED
- GREEN
- REFACTOR
とも。
このサイクルを繰り返す。以下テストを元に、
$ rails testを確認しながら、通るようにしていく。
テストを書き、通るように開発。簡単なTDD。require 'test_helper' class StaticPagesControllerTest < ActionDispatch::IntegrationTest # 省略 test "should get about" do get static_pages_about_url assert_response :success end endリファクタリング
「1匹いたら30匹いると思え」
金言。BUGでなくとも腐敗臭漂うだけでリファクタリングもの。
ネズミもGもBUGもスパゲッティコードも。早いうちからのリファクタリングが大事。3.4 少しだけ動的なページ
HTML内でheadのtitleタグを動的に表示し、TDDでつなぐ。
3.4.2
リファクタリング。
2,3回出てくる文字列を変数化
(インスタンス変数、文字列の式展開について、触れられている)3.4.3
DRY (Donot Repeat Yourself)
Rubyの原則。
共通部分をRailsの機能でまとめる。
/app/views/layouts/application.html.erb
上記に大枠のレイアウトを記述。
その他アクションのerb内の内容は、application.html.erb内に
<%= yield %>
と記述し、挿入する。3.5 最後に
コミットとデプロイ
masterブランチに変更をmerge
herokuにデプロイ$ git checkout master $ git merge 作業ブランチ名 # プッシュとデプロイ $ git push # github側 push $ rails t # herokuデプロイ前テスト $ git push heroku # heroku側 push $ heroku open # 確認デプロイ前に
rails testを実行。癖をつけるようにする。3.6 高度なセットアップ
3.6.1 minitest reporters
minitest-reporters (gem) でRailsのテストを見やすくする。
RED、GREENで色がつくようになる。3.6.2 Guardによるテストの自動化
Guardというgemでファイルを監視、自動テスト
$ bundle exec guard init # 初期化 $ bundle exec guard # 監視スタートguardのプロンプトが開く。
フルスキャンはそのままEnter。
終了は<C-d>でデタッチ。GuardはSpringサーバ(Railsの機能)を使うが、バグが有りプロセスが残ることが有るので、重いときには余計なものをkillする。
Linux killコマンド
プロセスのkill
$ ps aux | grep springパイプでgrepに渡し、springのみ抽出
pid(数字5桁)を指定してkill$ kill -15 12345 #pidはあくまで例ここのoptionで指定するシグナルは15がterminationで一緒か?
どうやらCPUごとに一部変わるそうで、x86なら-15でSIGTERM(termination)で終了できるらしい。
我が家のintelmacさんはx86かと思うので-15Springなら
1. 一括終了を最初に試す、
2. ダメならpkill$ spring stop $ pkill -15 -f プロセス名 # ダメなら所感
テスト駆動で書きながら、コントローラからビューに至るまでの流れをトレースできたように思う。
簡単なテストだが、まだ苦に思わない程度で済んでいる。
演習で2,3度同じような作業が繰り返されるので、少しずつ馴染めそう。
- 投稿日:2019-08-28T18:48:00+09:00
rails specで特定のファイルを指定してテストする
ググると
rails spec spec/models/user_spec.rbのようなのが出てきますが、実際は全部テスト実行されます。どこかのバージョンで変わったみたい。
うちのRails 5.2環境ではこれでいけた。
rails spec SPEC=spec/models/user_spec.rb
- 投稿日:2019-08-28T17:03:41+09:00
Docker Compose + Railsでgemが無いとエラーがでる。
背景
docker-composeでrails環境を構築したが起動せず。
gemが無いと言われているのでdocker-compose run 'コンテナ' bundle intallの実行で解決したが、なんでDockerfile内でbundle installしているのに再度bundle intsallしないといけないんだろうと疑問に思ったので調査してみました。構築時のファイル例
DockerfileFROM ruby:2.6.3 RUN apt-get update -qq && \ apt-get install -y build-essential \ libpq-dev \ postgresql-client &&\ rm -rf /var/lib/apt/lists/* # install nodejs RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ && apt-get install -y nodejs # install yarn RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn ENV APP_HOME /my_app RUN mkdir -p $APP_HOME WORKDIR $APP_HOME ADD Gemfile Gemfile ADD Gemfile.lock Gemfile.lock RUN bundle install ADD . $APP_HOMEdocker-compose.ymlversion: '3' services: web: build: . ports: - "3000:3000" command: [ "bash", "-c", "rm -f tmp/pids/server.pid; RAILS_ENV=development bundle exec rails s -b 0.0.0.0" ] volumes: - .:/my_app # volumeを使用してbundle installしてきたものを永続化 - bundle:/usr/local/bundle volumes: bundle:Gemfilesource 'https://rubygems.org' gem 'rails', '6.0.0'空のGemfile.lock
$ touch Gemfile.lockよくある構築コマンド例
# railsプロジェクトを作成 $ docker-compose run web bundle exec rails new . --force --skip-bundle # Dockerfileからイメージを作成 $ docker-compose build # コンテナ(rails)の起動 $ docker-compose upを実行すると
web_1 | bundler: failed to load command: rails (/usr/local/bundle/bin/rails) web_1 | Bundler::GemNotFound: Could not find gem 'sqlite3 (~> 1.4)' in any of the gem sources listed in your Gemfile. ...と出て起動しない。
コンテナに入ってgemを確認してみると
$ docker-compose run web ls /usr/local/bundle/gems actioncable-6.0.0 erubi-1.8.0 rack-test-1.1.0 actionmailbox-6.0.0 globalid-0.4.2 rails-6.0.0 actionmailer-6.0.0 i18n-1.6.0 rails-dom-testing-2.0.3 actionpack-6.0.0 loofah-2.2.3 rails-html-sanitizer-1.2.0 actiontext-6.0.0 mail-2.7.1 railties-6.0.0 actionview-6.0.0 marcel-0.3.3 rake-12.3.3 activejob-6.0.0 method_source-0.9.2 sprockets-3.7.2 activemodel-6.0.0 mimemagic-0.3.3 sprockets-rails-3.2.1 activerecord-6.0.0 mini_mime-1.0.2 thor-0.20.3 activestorage-6.0.0 mini_portile2-2.4.0 thread_safe-0.3.6 activesupport-6.0.0 minitest-5.11.3 tzinfo-1.2.5 builder-3.2.3 nio4r-2.5.0 websocket-driver-0.7.1 concurrent-ruby-1.1.5 nokogiri-1.10.4 websocket-extensions-0.1.4 crass-1.0.4 rack-2.0.7 zeitwerk-2.1.9
docker-compose buildのときにbundle installしたはずなのにgem 'rails'でインストールしたgemしか入っていない。(rails newで更新されたGemfileのgemがインストールされていない)なぜ起きるのか
下記条件で発生します。
bundle installしてきた内容をvolumeを使用してデータを永続化をしている。- rails newで--skip-bundleしている。
ポイント
docker-compose buildではvolumeと紐付かないdocker-compose runはvolumeと紐づく。原理
# 初回のbuildが走る。bundle installで ”railsのみ” がコンテナ内の/usr/local/bundleにインストールされる。 # volumeと紐づくので ”railsのみ” がvolumeに保存される。 $ docker-compose run web bundle exec rails new . --force --skip-bundle # 新しいGemfileのgemがコンテナ内の/usr/local/bundleにインストールされる。 # volumeと紐づかないのでvolumeは更新されない。 $ docker-compose build # volumeと紐付いたタイミングで/usr/local/bundleがvolumeに上書かれてしまう。 $ docker-compose up対応
docker-compose run bundle installでvolumeを更新する。- volumeを一回削除し再度作成することによって、volumeの中身を/usr/local/bundleと同じにする。
rails newする時に--skip-bundleを使用しない。疑問
docker-compose run bundle installをどうせ走らせるのならDockerfileからbundle installを削除していいのでは。
イメージとdocker-compsoeを1セットと考えるとそう思いますが、同じイメージを使ってvolumeを使わないパターンもあり得るので
bundle installをDockerfileから削除するのが必ずしも正しいわけではないのかなと感じました。
開発する上で下記を意識すれば問題ないか思います。
- gemをvolumeで管理しない:
docker-compose buildでgemを管理する。- gemをvolumeで管理する:
docker-compose run 'コンテナ' bundle installでgemを管理する。(docker-compose buildでbundle installが走っちゃうのは我慢する?)さいごに
Qiitaとかにあるチュートリアルをそのまま実行して起動できなくてハマった方もいると思うので、少しでも参考になればと思います。
間違えや不足などあればご指摘頂ければと思います。
- 投稿日:2019-08-28T17:01:57+09:00
他言語経験者がRailsの案件にジョインしたときに、何を足掛かりにすべきか
はじめに
この記事はOmotesando.rb #50で、参加者から質問を募集して、LTを行うという企画の中で、未経験者・初学者からのRailsプロジェクトに参画する際の質問が多かったことから、「実際に案件に参画するときにどのようなキャッチアップをしていけばよいか」という観点で話してみようと思い立ち、作成しました。
対象読者・想定プロジェクト
Ruby/Railsのプロジェクトに参画したことのない、Ruby/Railsプロジェクト未経験なWeb技術者を対象としています。また、Ruby/Railsの知識については、Railsチュートリアルは一通り目を通しているという前提で書いています。また、想定しているプロジェクトとしては、既に案件はスタートしており、gitリポジトリの整備、環境等の整備が一通り終わっており、人の受け入れ態勢が整っているプロジェクトであることを想定しています。
最初の関門である、環境構築の部分から書こうと思ったのですが、ここはプロジェクトによって様々なケースがあり、ボリュームが大きくなりそうだったので、今回の記事の中ではスキップして、環境構築は完了したという前提で話を勧めます。全体を把握する
プロジェクトに初めて入った時に、最初にやるべきことは全体の把握です。というのも、現実のRailsプロジェクトはRailsチュートリアルのようにシンプルではありません。むしろ基本に忠実に作られていることの方が稀です。いくつかのRuby/Railsプロジェクトに参画した経験があれば、どの程度しっかり作られているのかの勘が利くのですが、Rails未経験者・初学者の場合、そのあたりの感覚がよく分からないため、まず関わるプロジェクトがどの程度基本を押さえて作られているのかを把握しておく必要があります。
全体を把握するのに、まず以下を見ておくとよいでしょう。
- Gemfile / Gemfile.lock
- routes.rb
- app以下、lib以下
- config/initializers以下
- spec、もしくはtest以下
Gemfile / Gemfile.lock
Railsでは多数のGem(ライブラリ)が使われていて、中規模ぐらいのRailsプロジェクトになってくると、依存するGemも含めて100以上のGemが使われていることも珍しくはありません。Railsチュートリアルでは、極力Gemを使わない構成になっているので、あまり触れることはありませんが、現実のプロジェクトではGemが大量に導入されています。
ライブラリによってはRailsの挙動を大きく変更するものがあったり、プロジェクトのルールとしてGem特有の記法を強制するものもあるので、まずどのようなGemが使われているのかを把握しておく必要があります。Gemfileの中のgemを調べるときはrubygems.orgから、調べたいGem名を入力して、詳細画面からgithubやHomepage等のサイトに飛んで、README.md等のドキュメントを参照します。初学者のうちは分からないGemが多いと思いますので、調べるのも大変でしょうが、経験が蓄積されてくると全体の作りやプロジェクトのルールなども見えてくるので、ざっくりと概要をつかんでおくとよいと思います。
以下は私がプロジェクトにジョインしたときにあったら注意すべきGemと対応例の一例です。
gem 対応例 devise 認証処理がある。ユーザ名・パスワードの管理のテーブルにUsers等が使われていると考えられるので、app/models以下からdeviseの文字列を検索する omniauth-xxxx 外部認証連携が存在する。config/以下に認証連携用の設定が書き込まれていると考えておく。 acts_as_paranoid フラグを立ててデータを消したことにする論理削除と呼ばれる概念がある。対象のモデルは強制的にdeleted_at is not nullのクエリが付加されるため、app/models以下からacts_as_paranoidの文字列を検索し、対象となるモデルを把握しておく。 paranoia 同上 ruby-grape ActionControllerではないAPIエンドポイントを持っている。app/以下からGrape::APIを検索して、場所を把握しておく。また、エンドポイントはroutes.rbに書かれていることが多いため、合わせて参照しておく。 sidekiq 実際のURLリクエストとは別タスクとして実行される非同期処理がある。perform / perform_laterなどの文字列を検索し、非同期処理の内容自体やトリガー部分を確認しておく。 resque 同上 sequel DB検索にActiveRecordを使っていない可能性がある。プロジェクトのルールを確認する。 composite_primary_keys データベースの主キーがidではない可能性がある。app/models以下でprimary_keyで検索し、各テーブルの主キーを確認する。 sassc-rails CSSの代わりにassets/stylesheetsにSASSが使用されている可能性がある。 haml-rails ERBの代わりにhamlが採用されている。hamlの記法を用いてViewを書く必要がある。 slim-rails ERBの代わりにslimが採用されている。slimの記法を用いてViewを書く必要がある。 simple_form Form Objectと呼ばれる概念が導入されている可能性がある。 一つ一つ詳細に見ている時間がないという場合には、そのGemがどういう用途で導入されているかぐらいは確認しておきましょう。
The ruby toolboxというサイトで、Gem名で検索するとGemのカテゴリが分かるので、大まかに使用用途を推測することができます。routes.rb
RailsではRESTful URLでリソースベースのアクセスになるようにURL設計をしていくのが一般的ですが、現実のプロジェクトがしがらみなくRailsの推奨される構成でURL設計されているかというと、そういうわけではありません。例えば他のプロジェクトから移行するようなリプレース案件では、以前のURLと整合性がとれるようにURLをマッピングしなおさなければいけませんし、Railsを良く知らない設計者の趣味ですべてのURLをPOSTで記述しなければならないというトンデモルールが強制されている可能性すらあります。routes.rbを読んで、まずRails一般的なURL設計になっているかどうかを理解しておく必要があります。
Rails GuidesのRailsルーティングを熟読し、URL定義のパターンを理解しておきましょう。普通にget/postなどのメソッドで個別に定義する表現、matchメソッドでパターンマッチさせる表現、resourcesを使った表現や、複数のresourcesメソッドをネスト構造にしたnested resourcesやnamespaceと組み合わせた表現など、色々あります。
routes.rbを読む前に
rake routesを叩いて、エンドポイントをざっくりと俯瞰しておきましょう。app以下、lib以下
app以下
app以下にはassets, controllers, models, views, helpers, mailersがRailsの標準のディレクトリとして作成されています。これらのディレクトリの中身については、後で詳しく確認するとして、その他にディレクトリが存在しないかを確認しましょう。例えばservicesというディレクトリが存在していたら、そのプロジェクトではServiceクラスという独自のレイヤが存在する可能性がありますし、formsというディレクトリが存在していたら、そのプロジェクトではForm Objectという独自のレイヤが存在する可能性があります。
いずれもmodelクラスやcontrollerクラスが混沌としないように、プロジェクトの誰かが導入したものですので、これらの独自のレイヤをどのようなケースで使うべきなのかについては、導入した人物がまだ在籍しているのであれば直接質問する。そうでなければ、既存のコードから、どのようなメソッドが定義されていて、どのようなケースで、どこから呼ばれるのか、については把握しておく必要があります。
ServiceクラスもForm Objectも賛否両論あるものですが、プロジェクトの中できちんとルールが統一されているのであれば、導入自体はあまり問題ではありません。問題となるケースとしては責務が曖昧である、もしくは使用用途を逸脱した神クラスになっている場合や、導入が中途半端であるものは使っていて、あるものは使っていないなどの混在が存在する場合です。そのような可能性も含めて、プロジェクトとして使うべきなのか・使わないべきなのかの意思統一をしておく必要があります。
参考文献
Railsで重要なパターンpart1:Sercice Object(翻訳)
Rails: Form Objectと#to_modelを使ってバリデーションをモデルから分離する(翻訳)lib以下
lib以下は古くからGemにするまでもないようなプロジェクトの内部だけで完結するプライベートなファイルの置き場として利用されています。よく見る例としてはomniauthの独自strategyのファイルの置き場や、隠れオレオレライブラリ、オープンクラスで既存の振る舞いを書き換えたモジュールなどが配置されていることがあります。プロジェクトのファイルはapp以下に並ぶので、見落としがちなのですがlib以下にファイルがある場合は、そのファイルがどこでrequireされていて、何をしているのかは簡単に把握しておくとよいでしょう。コードが分からなくても、git log / git blameや、チケットから目的が理解できる場合もあります。
config/initializers以下
config/initializers以下はRailsが起動するプロセスの中で呼び出されます。起動プロセスの詳細についてはRailsガイドのRailsの初期化プロセスに詳しく載っているので、そちらを参照してください。ここもlib以下と同様に、app以外でプロジェクトのファイルが配置される可能性があるため見落としがちなのですが、Gemの初期化処理や、lib以下に置いたファイルのrequire処理など、アプリケーションの重要な手掛かりとなるコードが置かれていることがあります。
spec(もしくはtest以下)
参画しているプロジェクトにテストコードが十分に書かれていれば、キャッチアップを早める足がかりとなります。テストコードがどの程度書かれているかについては、
rake statsで、本体コードとテストコードのコード行数の比率を見てみましょう。あくまで個人的な目安ですが、本体コードとテストコードが同程度書かれていれば、正常系程度の最低限のテストコードが用意されていると見込める。本体コードの2~3倍程度テストコードがあれば、十分な分量のテストコードが用意されていると判断しても良いでしょう。
注意点としては過去にはテストコードが用意されていたが、メンテナンスする文化がなくなり、現在はテストコードはFailするものばかりで役に立っていないようなケースもあるため、まずはテストコードを手元で実行して、全部Passするかの確認はしておきましょう。大抵のRailsプロジェクトはbundle exec rake specやbundle exec rspec spec/**/*_spec.rbで動くようになっていますが、特殊な初期化が必要なために起動は別のコマンドで行っていたり、巨大なプロジェクトではRSpecが多すぎるため、分割して実行しているような場合もあります。プロジェクトでどのようにテストコードを実行するかの手順は確認しておきましょう。app以下を詳細に確認していく
全体を軽く見通した後は、app以下の個別のファイルについて目を通していきます。
個別のファイルについて詳細に目を通すのは実作業に取り掛かる段にして、先に確認しておくのは以下のようなことです。app/controllers以下
- application_controller.rbに定義されている共通のコールバック
- application_controller.rbにMix-inされている各種モジュールの意味
- app/controllers/concernsディレクトリ以下にあるモジュール群
- controllers以下の各コントローラに定義されているコールバック
- controllers以下の各コントローラにMix-inされているモジュール
app/models以下
- application_record.rbに定義されている共通のコールバック
- application_record.rbにMix-inされている各種モジュールの意味
- app/models/concernsディレクトリ以下にあるモジュール群
- models以下の各モデルに定義されているコールバック
- models以下の各モデルにMix-inされているモジュール
- models以下の各のhas_one / has_many / belongs_toの対応関係
- 各種バリデーションの充足度
application_controller.rbやapplication_record.rbに定義されているコールバックはコントローラ・モデルに影響するため、個別のモデルだけを見ていても分からないような振る舞いをすることがあります。またRubyではMix-inと呼ばれる方法でinclude / extend / prepend等でモジュールが差し込まれることがあり、これがapplication_controller.rbやapplication_record.rbに入っていると、すべてのクラスで影響を受けるようになっています。
モジュールはGemによって利用可能なものだったり、concerns以下のディレクトリに配置されたものを呼び出したりするものが一般的なので、concernsディレクトリを見ておけば振る舞いを変えるようなモジュールを先に見つけておくことができるでしょう。
application_record.rbについては、Rails5以降で導入された概念なので、もしかすると
ActiveRecord::Base.include AwesomeModuleのような形でモジュールがincludeされているケースもあります。このような記述をしているときは、大抵イレギュラーな処理が挟み込まれているので、includeされているモジュールが何者なのかは把握しておけると良いです。コールバックについてはRailsチュートリアルにもあるので、細かい説明は不要かと思いますが、より詳細に知りたい場合はRailsガイドのActiveRecordコールバックに目を通しておきましょう。
バリデーションについては、プロジェクトによっては全く書かれていなかったり、とても厳密に記述していたりと記述がまちまちなので、参画するプロジェクトがどの程度しっかりと書かれているのかを見ておきましょう。ベースとなる設計書や、バリデーションのガイドラインがプロジェクトとして用意されているのであれば、当然それに従うのが良いと思います。
app/views以下
views以下については、コントローラとメソッドの対応が、ディレクトリとファイル名の関係になっていることが多いので、コントローラから追っていけば対応関係は大体把握できるので、特に留意点もないのですが、layoutsファイルにapplication.html.erb以外のファイルがある場合は、controller側からlayoutメソッドを呼び出している箇所を検索しておくとよいです。views以下で使われているテンプレートエンジンはプロジェクトによってerbだったり、slimだったり、hamlだったり、jbuilderだったり、rablだったりしますが、記述の仕方が違うだけで、最終的にはhtmlやjsonファイルに変換されるという点では本質的には同じことなので、記述方法は公式ドキュメントで学びましょう。
app/helpers以下
ActionView内でレシーバなしで呼び出されているメソッドがあれば、Gemのメソッド、もしくはapp/helpers以下に定義されている可能性が高いです。application_helper.rbにまとめて書かれていて、他のモジュールは空という場合もあります。Railsでは
config.action_controller.include_all_helpersを明示的にfalseにしない限り、どこのhelperに記述しても結果は同じということもあり、どのhelperに書くかはプロジェクト次第なところがあります。まずはhelpers以下のファイルをざっと読んでみて、どういう指針で定義されているかは見ておきましょう。app/assets以下、もしくはapp/javascript以下
まだ多くのRailsプロジェクトはapp/assets以下で管理されていると思いますが、最近はWebpackerなどを導入するプロジェクトもあり、app/javascript以下にJavascriptが配置されていることもあります。ビルド時に何か問題が発生したときに、sprocketsなのかwebpackなのかは知っておく必要があります。
まとめ
以上、Railsのプロジェクトに参画しておくときに見ておくとよいものを、簡単にまとめてみました。
ここまで一通り読んでおくと、エンドポイントから機能をたどる時は、routes.rb → app/controllers/ → app/models → app/viewsと辿って、該当の機能を追うことができますし、新しい機能を追加するときも、周りの記述方針と合わせることができます。Railsに慣れないうちは、残念ながら目の前にあるコードが全てだと思うので、良し悪しを判断することは難しいと思いますが、まずは全体的に一貫性のある、統一感のあるコードが書けるようになることから始めましょう。
- 投稿日:2019-08-28T16:00:11+09:00
Ruby on RailsのアプリをGAEでデプロイする方法
1.まずはじめに
ポートフォリオを作成する上で少しオリジナル性を出したくてherokuではなくGCPを利用しようとしたのがきっかけになります。
その中で一番時間を取らなさそうなGAEでアプリをデプロイすることにしましたのでその際にやったことを記述しております。2.準備したもの
2-1.rubyのバージョン
サーバーのrubyにバージョンとアプリのバージョンを揃えました。
※こちらでバージョンアップについて書いてます2-2.GitHubのレポジトリ
GitHubのレポジトリをクローンしますので必須になります。
2-3.app.yaml
ルートディレクトリーにapp.yamlファイルを作成しておきます。
app.yamlentrypoint: bundle exec rackup --port $PORT env: flex runtime: ruby3.GCP操作方法
3-1.GAE内での操作
クリックすると下記の画面になるかと思います。
その中の赤枠でカッコってあるものをクリックします。(Cloud Shellが起動されます)3-2.GitHubのクローン
Cloud Shellが起動したらまず初めに自身のレポジトリをクローンします。
$ git clone https://github.com/Nash-BETA/test.git Cloning into 'test'... remote: Enumerating objects: 8394, done. remote: Counting objects: 100% (8394/8394), done. remote: Compressing objects: 100% (6611/6611), done. remote: Total 8394 (delta 1502), reused 7935 (delta 1047), pack-reused 0 Receiving objects: 100% (8394/8394), 34.13 MiB | 9.60 MiB/s, done. Resolving deltas: 100% (1502/1502), done.3-4.GAEのgemのインストールおよびDBの作成
クローンが完了したらディレクトリを移動してアプリケーションコードを表示させます。
$ cd test $ cat app.yaml次にbundle installを行います。
$ bundle installDBの作成をします。
$ rake db:migrate3-5.サーバーの選択
GCPコマンドでアプリの作成およびサーバーの選択
$ gcloud app create You are creating an app for project [First project]. WARNING: Creating an App Engine application for a project is irreversible and the region cannot be changed. More information about regions is at <https://cloud.google.com/appengine/docs/locations>. Please choose the region where you want your App Engine application located: [1] asia-east2 (supports standard and flexible) [2] asia-northeast1 (supports standard and flexible) [3] asia-northeast2 (supports standard and flexible) [4] asia-south1 (supports standard and flexible) [5] australia-southeast1 (supports standard and flexible) [6] europe-west (supports standard and flexible) [7] europe-west2 (supports standard and flexible) [8] europe-west3 (supports standard and flexible) [9] europe-west6 (supports standard and flexible) [10] northamerica-northeast1 (supports standard and flexible) [11] southamerica-east1 (supports standard and flexible) [12] us-central (supports standard and flexible) [13] us-east1 (supports standard and flexible) [14] us-east4 (supports standard and flexible) [15] us-west2 (supports standard and flexible) [16] cancel Please enter your numeric choice:14を選択。(特に理由がないのですがus-east4を選択しました)
3-5.app.yamlファイルにシークレットコードの追加
$ bundle exec rails secret [シークレットキーが表示されます] $ vim app.yaml entrypoint: bundle exec rackup --port $PORT env: flex runtime: rubyvim上でoをタイピングして挿入モードにして、下記の様に追加する。
app.yamlentrypoint: bundle exec rackup --port $PORT env: flex runtime: ruby env_variables: SECRET_KEY_BASE: [シークレットキー]escキーを押して:wqを入力すれば、変更内容の保存完了
3-6.デプロイして完了
$ gcloud app deploy Updating service [default] (this may take several minutes)...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://Firstproject.appspot.com]これで完了
- 投稿日:2019-08-28T15:10:15+09:00
Rails 画像アップロード機能の実装方法 メモ
初めに
railsで画像をアップロードする機能を実装するには、carrierwaveというgemを使う方法があります。
今回、画像を投稿する機能について学習したので、自分なりにまとめておこうと思います。使用するgem
・Carrierwave
画像をアップロードするために必要な機能を追加するためのgem
※Carrierwaveの導入には「ImageMagick」がインストールされている必要があるので、
実装前に以下のコマンドを入力して置くといいかもです。$ brew install imagemagick・Minimagick
画像に対して、画像同士を合成したり、リサイズしたりと編集することができるようになるためのgem
実装
では実装に入っていきます。
1.まずは上記の2つのgemを扱えるようにするためGemfileに以下のように追記します。Gemfilegem 'carrierwave' gem 'mini_magick' #画像に対して処理を行う場合2.gemをGemfileに追記したのでターミナルで以下のコマンドを実行します。
$ bundle install3. 次にcarrierwaveを利用するためのアップローダーを作成します。carrierwaveを導入したことで以下のコマンドが利用できるようになったので、ターミナルで実行しましょう。
$ rails g uploader image ※imageの箇所は任意の名前でOKです。例:pictureなどするとapp/uploadersディレクトリ以下にimage_uploader.rbが作成されます。
このファイルに別途記述を行うことで、アップロードの仕方を設定できます。
※設定方法は下記5.以降を参照4.アップローダーが作成できたので、画像アップロード機能を実装したいモデルに対して編集を行っていきます。
モデル名.rb# app/models/モデル名.rb mount_uploader :image, ImageUploader上記を追記することで、アップローダーを任意のモデルに対して
マウントすることができました。
※マウント
取り付ける、搭載するなどの意味↑↑↑画像をアップロードする機能のみの場合はここまで↑↑↑
5.アップロードする画像に対して別途処理を行いたい場合は
以下の設定を行います。
3.で行ったrails g uploader imageで作成された
image_uploader.rbを確認し、
include CarrierWave::MiniMagickがコメントアウトされているので、これを以下のように解除しましょう。
コメントアウトを解除することでgem 'mini_magick'を使用することができるようになります。app/uploaders/image_uploader.rbclass ImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagickこれでmini_magickの機能が使用できるようになったので
例えば、image_uploader.rbの任意の箇所に以下のコードを追記すると、縦横比を維持したまま、width, heightを800pxにリサイズしアップロードすることができるようになります。app/uploaders/image_uploader.rbclass ImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick # ~省略~ process resize_to_fit: [800, 800] endおわりに
以上がgemのCarrierwaveとmini_magickを使用した画像のアップロード機能の実装になります。
画像の投稿はwebアプリケーションにおいて基本的な機能ですので抑えて置きたいと思います。使用したgemのGithub
・Carrierwave
https://github.com/carrierwaveuploader/carrierwave
・mini_magick
https://github.com/minimagick/minimagick
- 投稿日:2019-08-28T12:48:17+09:00
Rails6 のちょい足しな新機能を試す71(implict_order_column 編)
はじめに
(多分)Rails 6 に追加された新機能を試す第71段。 今回は、
implicit_order_column編です。
Rails 6 では、firstやlastで使われるソートのカラムをimplicit_order_columnで指定できるようになっています。
これは、id を UUID にしていた場合に、firstやlastが予測できる結果となるようにするためのようです。
(Rails 6.0.0 がリリースされましたが、確認当時は、 Rails 6.0.0.rc2 が最新でした。悪しからず)
Ruby 2.6.3, Rails 6.0.0.rc2, PostgreSQL 10.7 で確認しました。Rails 6.0.0.rc2 は
gem install rails -v 6.0.0rc2 --prereleaseでインストールできます。$ rails --version Rails 6.0.0.rc2今回は、 User モデルを作成して
rails consoleを使って確認します。プロジェクトを作る
rails new rails_sandbox --database postgresql cd rails_sandboxUser モデルを作る
bin/rails g model User nameid を UUID にする
id を UUID にするために、マイグレーションのファイルを変更します。
db/migrate/20190803221758_create_users.rbclass CreateUsers < ActiveRecord::Migration[6.0] def change enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto') #この行を追加 create_table :users, id: :uuid do |t| # id: :uuid オプションを追加 t.string :name t.timestamps end end endseed データを作成する
seed データを作成します。 name の昇順にデータを登録します。
db/seeds.rbUser.create(name: 'Andy') User.create(name: 'Bob') User.create(name: 'Cindy')マイグレーションを実行し seed データを登録する
bin/rails db:create db:migrate db:seedrails console で確認する
rails consoleで確認します。
User.firstを実行してみます。irb(main):001:0> User.first User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]] => #<User id: "5da612ca-f055-4678-9c87-927b0a1a28d2", name: "Cindy", created_at: "2019-08-03 22:24:51", updated_at: "2019-08-03 22:24:51">結果が Cindy になってしまいました。 (結果は必ず Cindy になるとは限りません。)
SQL を確認するとidでソートされていることもわかります。
User.lastを実行してみます。irb(main):002:0> User.last User Load (0.5ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]] => #<User id: "fe31d9a5-8de0-4d35-8a6f-183902f2884b", name: "Bob", created_at: "2019-08-03 22:24:51", updated_at: "2019-08-03 22:24:51">結果が Bob になりました。
SQLを確認するとidの降順にソートした最初のレコードが検索されているのがわかります。implicit_order_column を使う
User モデルを変更して implicit_order_column で
:nameを指定してみます。app/models/user.rbclass User < ApplicationRecord self.implicit_order_column = :name endrails console で確認する
修正を反映させるため
reload!します。irb(main):003:0> reload! Reloading... => true
User.firstの結果は、 Andy になります。nameの昇順でソートされていることがわかります。irb(main):004:0> User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."name" ASC LIMIT $1 [["LIMIT", 1]] => #<User id: "cc7ff0b1-4dc3-47f4-a5cd-259a804c9690", name: "Andy", created_at: "2019-08-03 22:24:51", updated_at: "2019-08-03 22:24:51">
User.lastの結果は、 Cindy になります。nameの降順でソートされていることがわかります。irb(main):005:0> User.last User Load (0.6ms) SELECT "users".* FROM "users" ORDER BY "users"."name" DESC LIMIT $1 [["LIMIT", 1]] => #<User id: "5da612ca-f055-4678-9c87-927b0a1a28d2", name: "Cindy", created_at: "2019-08-03 22:24:51", updated_at: "2019-08-03 22:24:51">複数カラムの指定はできない
app/models/user.rbself.implicit_order_column = %i[name created_at]とした場合は、 ActiveRecord::StatementInvalid エラーになりました。
まあ、そりゃそうですよね。 複数形 (implicit_order_columns) じゃないですもんね。irb(main):011:0> User.first Traceback (most recent call last): 2: from (irb):11 1: from (irb):11:in `rescue in irb_binding' ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column users.[:name, :created_at] does not exist) LINE 1: SELECT "users".* FROM "users" ORDER BY "users"."[:name, :cre... ^試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try071_implicit_order_column参考情報
- 投稿日:2019-08-28T10:55:34+09:00
scaffoldの使い方
scaffoldとは
モデルやコントローラー、ビューを作っていき、さらに必要なルーティングを作成していく必要があるがrailsには簡単にアプリケーションの雛形を作ってくれる機能があり、それがscaffoldです。scaffoldを使うことで素早くrailsアプリケーションを作ることができる。
作成手順
rails new sample作成後、該当ディレクトリへ移動する
cd sample移動後に下記コマンドを実行
rails generate scaffold モデル名 カラム名1:データ型1 カラム名2:データ型 2 …examplerails g scaffold user name:string age:integer指定できる型一覧
- string : 文字列
- text : 長い文字列
- integer : 整数
- float : 浮動小数
- decimal : 精度の高い小数
- datetime : 日時
- timestamp : タイムスタンプ
- time : 時間
- date : 日付
- binary : バイナリデータ
- boolean : Boolean
作成されるもの
- マイグレーションファイル
- db/migrate/xxxxxxxxx_create_users.rb
- モデル
- app/models/user.rb
- コントローラー
- app/controllers/users_controller.rb
- ルーティング
- config/routes.rb
- ビュー
- app/views/users/index.html.erb
- app/views/users/edit.html.erb
- app/views/users/show.html.erb
- app/views/users/new.html.erb
- app/views/users/_form.html.erb
routes.rbでは7つのアクションが自動的に定義される。
rake db:migrate
テーブルの作成
以上
- 投稿日:2019-08-28T10:24:40+09:00
herokuでのデプロイ
はじめに
herokuを使ってデプロイができたので、その方法を記録として残しておく。
準備
gemfileの設定
Gemfile# sqlitesqliteをコメントアウト
Gemfilegroup :production do gem 'pg' end上記コードは
gemfile最下部に記載環境ごとのデータベースの設定変更を行う
開発時にはmysql使用、本番環境(heroku)ではPostgreSQL(pg)を使用
環境にあうように設定ターミナルbundle installconfig/datebase.ymlの設定
config/database.ymlproduction: <<: *default adapter: postgresql #postgreSQLに接続 encoding: unicode #文字コード pool: 2 #データベース接続可能上限数config/environments/production.rbの設定
config/environments/production.rbconfig.assets.compile = true # falseとなっているのでtrueにするbinフォルダ内の設定
binフォルダ内の各ファイル.rb#!/usr/bin/env ruby #ここに記載のバージョンを削除Git
gitにコミットをしておく
heroku
herokuに登録しておく
会員登録後、
https://devcenter.heroku.com/articles/heroku-cli
上記から個人の使用にマッチするものをダウンロードターミナル操作
$heroku login上記コマンド入力後に下記コマンドが表示されるので適当にキーを叩く
Press any key to open up the browser to login or q to exit:
ターミナル上に上記画像の表示が現れ、自動でブラウザが開かれるのでlog inする
ログイン後、再びターミナルへ
$heroku create アプリ題名デプロイ
$git push heroku masterデプロイ成功後に下記コマンドの実行
heroku run rails db:migrate上記コマンド入力後に先程、実行した下記コマンドで表示されるurlにログインすれば、自分の作成したアプリが表示されるはず!!
$heroku create アプリ題名補足
git push heroku master時にCould not find 'bundler'のエラーが発生しました。私は色々とググった結果
rubyとbundlerのバージョンをあげることで解決しました。最後に
コマンドの一覧やデプロイ時のエラー対処方法なども調べてまとめていきたいです。
デプロイは凄い大変なイメージがありましたがherokuでのデプロイは操作が簡単、userのやることが少なくて楽だという印象を受けました。参考記事
https://qiita.com/amuyikam/items/989300248f471020ca18
https://qiita.com/tktcorporation/items/0ef8c930fc18ce72c301
- 投稿日:2019-08-28T06:06:55+09:00
Win上でRails+Bootstrapを使用した時に出てくるExecJS エラーを直したい(直す)
はじめに
WindowsでRailsアプリケーションを作成し、
Bootstrapを導入したところ、ExecJSエラーが出て、起動しない。
- Windows 10 proもしくはhomeで確認
- Railsのバージョンは5.2.3
- Rubyのバージョンは2.6.3最近Rails6にアップデートされたので、この記事は今後使えなくなる可能性があります。
詳細
こんなエラーがターミナル上で出てるのではないでしょうか。
ExecJS::ProgramError in Home#index Showing C:/Source/Repos/graph-tutorials/ruby-test/app/views/layouts/application.html.erb where line #8 raised: identifier '(function(opts, pluginOpts) {return eval(process' undefined Rails.root: C:/Source/Repos/graph-tutorials/ruby-test解決策
僕はこのissueをみて使えるようになりました。
https://github.com/twbs/bootstrap-rubygem/issues/157やり方
1.Gemfileの修正
duktapeのgemを探してコメントアウト、もしくは削除します。2.Node.jsのインストール(Node.jsがインストールされていない場合のみ)
Node.jsの公式ページからダウンロードします。
https://nodejs.org/ja/download/
推奨版と最新版があって、最新版をダウンロードしたくはなりますが、
ここはその気持ちを押し殺して推奨版をダウンロードします。その後インストールをしてください。
その後Windowsで環境変数の設定を開き、PATHを通してください。
PATHの通し方はこちらを参考にするといいです。
いろんな方法がありますね。
https://qiita.com/yuki12/items/9723f60907508b11504b最後にコマンドプロンプト or Gitbash or PowerShellを開いて
下記のコマンドを入力し、バージョンが表示されるか確認してください。$ node -v
config/boot.rbに追記する。下記のコードを貼り付けてください。
runtime時にnodeを使うように指示します。config/boot.rbENV['EXECJS_RUNTIME'] = 'Node'サーバーを再起動
サーバーを再起動して、エラーが出ないか確認してください。
- 投稿日:2019-08-28T06:06:55+09:00
Win上でRails+Bootstrapを構築の時に出てくるExecJS エラーを解決したい(解決する)
はじめに
WindowsでRailsアプリケーションを作成し、
Bootstrapを導入したところ、ExecJSエラーが出て、起動しない。
- Windows 10 proもしくはhomeで確認
- Railsのバージョンは5.2.3
- Rubyのバージョンは2.6.3最近Rails6にアップデートされたので、この記事は今後使えなくなる可能性があります。
詳細
こんなエラーがターミナル上で出てるのではないでしょうか。
ExecJS::ProgramError in Home#index Showing C:/Source/Repos/graph-tutorials/ruby-test/app/views/layouts/application.html.erb where line #8 raised: identifier '(function(opts, pluginOpts) {return eval(process' undefined Rails.root: C:/Source/Repos/graph-tutorials/ruby-test解決策
僕はこのissueをみて使えるようになりました。
https://github.com/twbs/bootstrap-rubygem/issues/157やり方
1.Gemfileの修正
duktapeのgemを探してコメントアウト、もしくは削除します。2.Node.jsのインストール(Node.jsがインストールされていない場合のみ)
Node.jsの公式ページからダウンロードします。
https://nodejs.org/ja/download/
推奨版と最新版があって、最新版をダウンロードしたくはなりますが、
ここはその気持ちを押し殺して推奨版をダウンロードします。その後インストールをしてください。
その後Windowsで環境変数の設定を開き、PATHを通してください。
PATHの通し方はこちらを参考にするといいです。
いろんな方法がありますね。
https://qiita.com/yuki12/items/9723f60907508b11504b最後にコマンドプロンプト or Gitbash or PowerShellを開いて
下記のコマンドを入力し、バージョンが表示されるか確認してください。$ node -v
config/boot.rbに追記する。下記のコードを貼り付けてください。
runtime時にnodeを使うように指示します。config/boot.rbENV['EXECJS_RUNTIME'] = 'Node'サーバーを再起動
サーバーを再起動して、エラーが出ないか確認してください。
- 投稿日:2019-08-28T04:56:19+09:00
Ruby on Rails + MySQLのアプリケーションをHerokuにデプロイする手順(Heroku.yml)
どんな記事か
- Rails+MySQLのアプリケーションをDockerで環境構築した人が、herokuで本番環境を構築できるようになる。
対象読者
- DockerでRails+MySQLを起動して、「Yay! You’re on Rails!」を表示している人。
- 本番環境にも反映して誰からにも見せたい人。
- デプロイのエラーで躓いて困っている人。
完成後のイメージと各ツールのバージョン
今回こちらの実機で確認しました。
- macOS Mojave 10.14.5
- Ruby 2.6.3
- MySQL 5.7
- Heroku 7.29
- Git 2.20.1そもそもどうやって、DockerでRails+MySQLの環境構築をすればいいのという方へ??
こちらのgithubのページで、確認してもらえたらと思います。。
https://github.com/YutakaYamasaki/docker_setup_rubyonrailsちなみに、今回のソースは全て上記の手順を行なった後、デプロイする形になります。
やること
- Railsのアプリケーション修正、追加
- Herokuにデプロイ
Railsアプリケーションのファイルを修正、追加する。
Gemfile(修正、追加)
ここで、mysqlとpgのgemを修正、追加します。
開発環境ではMySQLを使用しますが、本番環境(デプロイ)ではPostgreSQLを使用していきます。変更前と変更後です。
Gemfile##変更前 gem 'mysql2', '>= 0.4.4', '< 0.6.0' ##変更後 gem 'mysql2', '>= 0.4.4', '< 0.6.0', groups: %w(test development), require: false gem 'pg', '~> 0.19.0', group: :production, require: falsedatabase.yml(修正、追記)
こちらのファイルにも、本番環境ではPostgreSQLを使用するので、下記のように修正してください。
productionの項目がなければ、追記してください。
項目があれば、削除してください。database.ymlproduction: <<: *default adapter: postgresql encoding: unicode pool: 5heroku.yml(新規ファイル作成)
heroku.ymlファイルを作成します。
アプリのファイルの直下に、heroku.ymlファイルを作成して、下記のように記載してください。heroku.ymlbuild: docker: web: Dockerfile run: web: bundle exec puma -C config/puma.rbこれで各ファイルの編集が完了しました。
Docker側にもファイルの変更を反映させておきましょう。$ docker-compose build誤字脱字がないか確認した後に、
Herokuへデプロイを進めましょう!Herokuにデプロイ
基本全てターミナルで行います。ターミナルの操作に慣れているという前提で進めていきます。
Herokuにログイン
下記のコマンドを打ちます。
途中でエンターキーを押すとブラウザが立ち上がるので、ブラウザで操作してログインが終わると、
ターミナルの方でもログインができます。$ heroku login heroku: Press any key to open up the browser to login or q to exit: ##ここでエンターキーを押すとブラウザが開くので、ログインを行う。 ##ブラウザでログインができてターミナルに戻ると、下記が表示されるはず Opening browser to https://cli-auth.heroku.com/auth/browser/************** Logging in... done Logged in as *******@email.comHerokuにアプリケーションを作成する。
下記のコマンドを打ちます。
すると、URLが自動発行されます。$ heroku create ##ちなみにcreateの後にスペースキーを押して、好きなアプリ名を入力すると、そのアプリ名のURLが自動発行されます。お試しあれ Creating app... done, ⬢ ******* https://******.herokuapp.com/ | https://git.heroku.com/*******.gitHeroku側でPostgreSQLを使用する。
Heroku側でPostgreSQLを使用するように設定します。
クレジットカードを登録したり、有料会員になるとMySQLも使用できます。$ heroku addons:create heroku-postgresql:hobby-dev Creating heroku-postgresql:hobby-dev on ⬢ ******... free Database has been created and is available ! This database is empty. If upgrading, you can transfer ! data from another database with pg:copy Created postgresql-transparent-70433 as DATABASE_URL Use heroku addons:docs heroku-postgresql to view documentationちなみに、このURLにアクセスしてもエラーが出てきます。なぜなら、アプリがHeroku側にないから。
これからアプリをheroku側にアップロードして、デプロイします。Heroku.ymlを使ってデプロイする。
Herokuではコンテナ諸々をデプロイすることができます。
その中で、デプロイする方法は2通りあります。
- Container Registry GAを使用してデプロイ
- Heroku.ymlを使用してデプロイ←今回はこちらを使用。詳細は下記見てもらえると
https://devcenter.heroku.com/categories/deploying-with-docker
まずは、Heroku側でStackをcontainerにセットします。$ heroku stack:set containerその後、下記のコマンドを打って、デプロイをしましょう。
$ git init $ git add . $ git commit -m "******" $ git push heroku masterデプロイできたか確認する。
下記のコマンドでブラウザが立ち上がり、Railsのアプリケーションがデプロイされているか確認します。
$ heroku open
- 投稿日:2019-08-28T00:38:22+09:00
大学2年生のオリジナルWebアプリケーション開発7日目
今日の流れ
- Eventモデル
- Event一覧の表示
- dateの短縮日付表示
改めて僕の開発しているアプリをご紹介しますと、出欠管理アプリを開発しています。
そのきっかけはサークルの出欠管理が非効率だったので、せっかくだから自分で作ってみようというところから始まりました。管理する出欠は何かしらのイベント(Event)なので、Eventモデルを構築することを考えました。
1. Eventモデル
Eventモデルには何が必要なのか考えた結果、次のようなカラムとそのデータ型を選択しました。
カラム名 データ型 user_id references event_name string date datetime memo text カラム以外は基本的にRailsチュートリアルのmicropostをeventに置き換えただけとなっています。
次にイベントモデルのバリデーションを考えました。
user_id, event_name, dateには存在の、event_nameとmemoには文字数制限のバリデーションを施しました。そして、userとeventを関連付けるためにbelong_to/has_manyを利用しました。
models/event.rbbelongs_to :usermodels/user.rbhas_many :events, dependent: :destroy2. Event一覧の表示
次にユーザーのページにそのユーザーの企画したEvent(フォームから作成予定)を一覧表示させました。
この部分はRailsチュートリアル第13章の13.2にあたります。
micropostの部分をeventに変更させるだけでしたが、後述するdateの表示で手間取りました。3. dateの短縮日付表示
今日最も時間がかかったのはこの部分です。Railsチュートリアルにはdatetimeや日付表示に関して記述はなかったので自分で模索しながら進めました。
Event一覧中のdateの表示は短縮日付(正確な呼び名は知りません)、yyyy/mm/dd(曜日)という形で表示したかったのです。
調べているとすぐにstrftimeというメソッドを用いればよいことがわかりました。
しかし、以下の多くの要因で混乱してなかなかうまく表示されませんでした。具体的には、yyyy/mm/dd(曜日)としたいのに、2019-08-026 17:52:54 +0900みたいな感じで表示されていました。
要因:
- strftimeで作られるオブジェクトはStringクラスであること
- ブロック付きメソッドを用いていた
- 時間を表すクラスには、Timeクラス, Dateクラス, DateTimeクラスなど複数存在すること
一つ目の要因
まず、一つ目の要因への策として、一回dateカラムのデータ型をstringに変更して解決はできたのですが(その方法が気になる方はこちら)、後のフォームのことを考えてやはりdatetimeでいくことにしました。
最終的な結論は、viewで表示される2019-08-026 17:52:54 +0900をview側でyyyy/mm/dd(曜日)表示にしてしまうということです。これに気づいたことが大きかったです。これらのサイトを参考にさせていただきました。
https://www.javadrive.jp/ruby/date_class/index5.html
https://techracho.bpsinc.jp/hachi8833/2016_10_06/25960二つ目の要因
db/seeds.rb40.times do |n| endの "n" が混乱させてきたのですが、まあこれはdb/seeds.rbの中でRailsチュートリアルと同様にしていれば平気でした。
とりあえず、rails cを多用して実験しまくりました!三つ目の要因
こちらのサイトなどを拝見したところ、どうも時間を扱うクラスは奥が深くここではすべてを理解することはやめました。
試行錯誤していると、dateのデータ型はdatetimeですが、timeとかでもうまくRailsがやっていてくれている感じはしていました。
まあ、面倒くさいという理由からすべての時間はto_datetimeでdatetimeに無理やり直しました。
最終的に
最終的には次のようにした結果、うまくいきました。
db/seeds.rbusers = User.order(:created_at).take(2) 40.times do |n| event_name = "練習#{n}" date = n.days.ago.to_datetime # datetimeに変更 memo = "楽しみましょう" users.each { |user| user.events.create!(event_name: event_name, date: date, #seed.rbでstrftimeを使うとstringとなるが、viewで(date)time?に変更されてしまう(2019-08-026 17:52:54 +0900の表示になる) memo: memo) } endviews/events/_event.html.erb<% d = event.date %> <%# この時点ではdatetimeとして受け取っている %> <% wd = ["日", "月", "火", "水", "木", "金", "土"] %> <span class="date">日時:<%= d.strftime("%Y/%m/%d(#{wd[d.wday]})") %></span> <%# datetimeのdをここでstrftimeを用いてstringに変更している(yyyy/mm/dd(曜日)の表示になる) %>終わりに
今日から本格的にオリジナルの部分を作り始めました。まぁRailsチュートリアルの第13章を参考にしているのですが。とにかく大変で時間がかかるのですが、その大変さを乗り越えるために必要なものとして今回気づいたのは
- ググる力
- rails c
が大事だということ。
ググる力はもちろんですが、Railsチュートリアルでなんとなく使っていたrails cがこんなに大事だとは思いませんでした。コンソールでの実験がいかに強力かわかりました。
明日はフォームの作成をしようと思います。個人的にはまだモデルや、モデルのカラムが足りないかなと思っていて、今後はEventにパスワード?やShareLinkモデルやAnswerモデルなんかが必要になるのかと思っていますので、モデルを考える時間がさらに必要だと考えています。とりあえず今日はこの辺で。









