20210506のRailsに関する記事は23件です。

rails 6.1.3.2の` ActionView::Template::Error: Please use symbols for polymorphic route arguments.`が発生する理由と対処

rails 6.1.3.2以降でActionView::Template::Error: Please use symbols for polymorphic route arguments.場合の原因と対処について 原因 脆弱性CVE-2021-22885の対応の影響で既存のソースコードでrails 6.1.3.2, 6.0.3.7, 5.2.4.6, 5.2.6にバージョンアップすると既存のコードでActionView::Template::Error: Please use symbols for polymorphic route arguments.が発生する可能性があります。 脆弱性対応について CVE-2021-22885のセキュリティーパッチです。 redirect_toやpolymorphic_urlなど動的にURLを生成するヘルパーメソッドで意図しないURLが作成される可能性があり脆弱性になるとの事です。 See: https://weblog.rubyonrails.org/2021/5/5/Rails-versions-6-1-3-2-6-0-3-7-5-2-4-6-and-5-2-6-have-been-released/ 脆弱性に対するrailsの対応 polymorphic_urlの引数record_or_hash_or_arrayにStringのArrayを渡すような実装があると例外ActionView::Template::Error: Please use symbols for polymorphic route arguments.を発生させる様になりました。 def handle_list(list) record_list = list.dup record = record_list.pop args = [] route = record_list.map do |parent| case parent when Symbol parent.to_s when String raise(ArgumentError, "Please use symbols for polymorphic route arguments.") when Class args << parent parent.model_name.singular_route_key else args << parent.to_model parent.to_model.model_name.singular_route_key end end See: https://github.com/rails/rails/blob/c4c21a9f8d7c9c8ca6570bdb82d64e2dc860e62c/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb#L284-L303 修正PR 影響 polymorphic_urlはform_withなどたくさんのメソッドの内部で使用されているので例えば以下のようなroutingがあった場合に、 config/routes.rb namespace :admin do resources :users end #=> /admin/users/ このパスに対してform_withヘルパーを使用する場合にmodel引数の配列に文字列型を指定するとエラーが発生します。 <%= form_with model: ['admin', user] do |f| %> #=> ActionView::Template::Error: Please use symbols for polymorphic route arguments. 対処方法 上記の例の場合はmodel引数の配列に指定していた文字列をシンボル変更します。 - <%= form_with model: ['admin', user] do |f| %> + <%= form_with model: [:admin, user] do |f| %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【rails】seeds 作成時の "NoMethodError: undefined method `テーブル名1' for #<テーブル名2:0x000055f5fcc6c580> エラーの解決

エラー原因 結論からいうと、has_many :テーブル名を書いていないからエラーが起こりました。 エラー状況 下記のような状態で、rails db:seedを実行したところ、 NoMethodError: undefined method 'products' for #<User:0x000055f5fcc6c580>が発生。 user = User.create!( last_name: "山田", first_name: "太郎", email: "user1@example.com", password: "password", ) product = user.products.create!( product_name: "りんご", description: "新鮮なりんごです", user_id: user1.id, ) 実行結果 : エラー発生 `NoMethodError: undefined method 'products' for #<User:0x000055f5fcc6c580>` 解決 models/user.rb に下記のように書くことで解決。 has_many :products, dependent: :destroy テーブル同士の関連付けが出来ていなかった為、エラーしていました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ユーザ登録機能の実装(deviseを使用して説明)ビュー作成〜

ビューの作成 deviseインストールからuserモデル作成までは下記の記事にて書かせていただきました。 今回はビューの作成を行います。 deviseでログイン機能を実装すると、ログイン/サインアップ画面が自動的に生成されます。 しかし、ビューはファイルは生成されていません。 なので、コマンドでビューファイルを生成します。 ターミナル . rails g devise:views ビューファイルが生成されました。 サインアップのビュー app/views/devise/registrations/new.html.erb ログインのビュー app/views/devise/sessions/new.html.erb コントローラーについて ビューファイルができ、前記事でモデルを作成し、ルーティングの自動で生成される事を確認しました。 残るはコントローラーです。 deviseのコントローラーはGem内に記述されているため、編集することができません。 そのため、applicationコントローラーで記述します。 applicationコントローラーはコントローラー内での頂点です。全てはここから始まります。(言い切ってはいけない) 全てのコントローラーの1行目には下記が記述されています。 controller.rb class HogeController < ApplicationController applicationコントローラーでストロングパラメーターを設定します。 app/controllers/application_controller.rb class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? private def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :birth_day]) end end 1つづつ確認していきます before_action :configure_permitted_parameters, if: :devise_controller? before_actionで全てのコントローラーの前に動き、またif: :devise_contoroller?でdeviseにまつわる事が起きたときに作動します。 private def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :birth_day]) end end deviseにおけるストロングパラメーターです。deviseの「ログイン」「新規登録」などのリクエストからパラメーターを取得できます。 このメソッドとpermitメソッドを組み合わせることにより、deviseに定義されているストロングパラメーターに対し、追加したカラムも含めることができます。(email,passwordはすでに定義されているため)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Gem パスワードを暗号化するbcyptの使い方

bcyptとは パスワードを暗号化してセキュリティを向上させるためのGemです。 bcyptのインストール Ruby on RailsのGemfileの中にコメント付きで既に記述されていので そのコメントアウトを外してbundle installすることでインストールすることができます。 % bundle install bycypt bycyptでは主に2つのメソッドを使うことができるようになります。 has_secure_passwordメソッド authenticateメソッド ・has_secure_password モデル内に1行書くことにより、passwordとpassword_confirmationという属性を使うことができます。 maigationファイルにカラムを追加する場合はpassword,password_confirmationではなく 20210416072618_add_password_to_users.rb class AddDetailsToTitles < ActiveRecord::Migration def change add_column :users, :password_digest, :string end end とする必要があるので注意です。 passwordを格納するデータベースのテーブルにはpassword_digestというカラムを作成しておくと、 passwordとpassword_confirmationで入力したパスワードが一致していれば password_digestカラムに暗号化してパスワードを格納することができるようになります。 viewファイルにpasswordとpassword_confirmationをフォームで送るだけでbcyptが暗号化してくれます。 _form.erb <%= form_with model: @user do |f| %> <%= f.label :password %> <%= f.password_field :password %> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation %> <% end %> ・authenticateメソッド authenticateメソッドはパスワードを認証するためのメソッドで正しいパスワードを入力するとtrueを返し、間違ったパスワードを入力するとfalseを返します。 パスワードのバリデーションは標準で装備されています。 アプリを作って試してみる % rails new password_app % cd password_app % rails db:create Gemfile # gem 'bcrypt', '~> 3.1.7' を外して % bundle install Userモデルを作成してpassword_digestカラムを作成します。 % rails g model user password_digest:string 作成できたら % rails db:migrate userモデルにhas_secure_passwordを書きます。 models/user.rb class User < ApplicationRecord has_secure_password end rails consoleで動作確認します。 $ rails c 間違ったパスワードを入れるとfalseが返ってきて 正しいパスワードを入れると情報が返ってきています。 irb(main):001:0> u = User.new (1.3ms) SELECT sqlite_version(*) => #<User id: nil, password_digest: nil, created_at: nil, updated_at: nil> irb(main):002:0> u.password = "1234" => "1234" irb(main):003:0> u.save (0.2ms) begin transaction User Create (3.6ms) INSERT INTO "users" ("password_digest", "created_at", "updated_at") VALUES (?, ?, ?) [["password_digest", "$2a$12$PaXO7LLKIqWGIXFhpkZcgOPSv2H.Mrmol6XwvI0aYMxrYdCFlmQCS"], ["created_at", "2021-05-06 13:04:13.549990"], ["updated_at", "2021-05-06 13:04:13.549990"]] (1.6ms) commit transaction => true irb(main):004:0> u.authenticate("3333") => false irb(main):005:0> u.authenticate("1234") => #<User id: 4, password_digest: [FILTERED], created_at: "2021-05-06 13:04:13", updated_at: "2021-05-06 13:04:13"> 以上です。 参考サイト Qiita Railsにおけるパスワードの扱い方(BCrypt) FREE SWORDER Railsアプリのパスワードを暗号化する方法〜bcryptの使い方〜 Rails Tutorial
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on rails でLine push(プッシュ)メッセージ(ブロードキャスト)を送る

概要 LINEAPIでメッセージを送る場合、応答メッセージとプッシュメッセージの大きく2つに分けられます。 応答メッセージはオウム返しのような、ユーザーのアクションに対して応答するタイプで、プッシュメッセージはユーザーのアクションに関係なく、サーバーサイドからプログラムを実行し、メッセージを送れるタイプです。 ネット上の記事を見渡すと応答メッセージに関するLINEボットの記事がたくさんあるのに対し、プッシュメッセージについて書かれた記事があまりなかった印象を受けたのに加えある一定の需要がありそうなので書き残しておきます。 環境 Ruby(2.2以上) Rails(5以上) 今回やりたいこと 公式のドキュメントに書いてあるようにヘッダーにアクセストークン、bodyに送りたい相手のユーザーID(ブロードキャストの場合不要)、メッセージの内容を格納してAPIを叩く(postする)ことでメッセージを送信できます。 このcurlコマンドの内容をRubyで書き換えることが今回のゴールです。 以上のことを踏まえて手順を細分化すると 1. Line Developerで自分のアクセストークンとユーザーIDを取得 2. curlコマンドを叩いてメッセージが自分のアカウントに送信できているか確認 3. Rubyでコードを書く。 4. リファクタリング(出来たら) という流れになります。 一つ一つ見ていきましょう。 1.Line Developerで自分のアクセストークンとユーザーIDを取得 LINE Developerのマイページに書いてあるYour user IDが自分のアクセストークンに該当し Channel Access Tokenがアクセストークンに該当します。 詳しい記事は割愛しますので他の記事や公式ドキュメントをご参照ください。 2.curlコマンドで確認 ブロードキャスト(友達全員に送信)の場合 curl -v -X POST https://api.line.me/v2/bot/message/broadcast \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer {channel access token}' \ -d '{ "messages":[ { "type":"text", "text":"Hello, world1" }, { "type":"text", "text":"Hello, world2" } ] }' この該当部分(ヘッダーのアクセストークン)を変更しメッセージが遅れてるか確認。 マルチキャスト(特定の複数ユーザーに送信)の場合 curl -v -X POST https://api.line.me/v2/bot/message/multicast \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer {channel access token}' \ -d '{ "to": ["U4af4980629...","U0c229f96c4..."], "messages":[ { "type":"text", "text":"Hello, world1" }, { "type":"text", "text":"Hello, world2" } ] }' この場合は送りたい相手のユーザーIDが必要です。 自分のIDはマイページから確認できますが友達のIDは友だち追加やメッセージの受信をトリガーにIDを取得できるコードを書いて格納するのが一般的です。 その他の送信方法は公式ドキュメントをご参照ください。 3.Rubyで書き換える 実際のコード(ブロードキャスト) message.rb class Message def broad_push require 'net/http' require 'uri' require 'json' token = ENV["LINE_CHANNEL_TOKEN"] # post先のurl uri = URI.parse('https://api.line.me/v2/bot/message/broadcast') http = Net::HTTP.new(uri.host,uri.port) http.use_ssl = true # Header headers = { 'Authorization'=>"Bearer #{token}", 'Content-Type' =>'application/json', 'Accept'=>'application/json' } send_message = #自分が送りたいメッセージ # Body params = {"messages" => [{"type" => "text", "text" => send_message}]} response = http.post(uri.path, params.to_json, headers) end end 今回はブロードキャストで実装しましたが他のマルチキャスト等も流れはほとんど同じで、bodyとurlを変更するだけで実装できます。 今回は環境変数を格納するにあたり.envファイルで管理しています。(githubに間違えてプッシュしないように) Rails環境下でしか使えないのでお気をつけください。 rake taskで定期実行 push_message.rb namespace :push_message do desc "line ブロードキャスト機能で友達全員に明日の予定をプッシュする" task tomorrow_plans: :environment do message = Message.new message.broad_push end end Herokuなどで決まった時刻に定期実行したい場合はrake taskで実行できるようにtaskに切り出しておくと便利です。 今回は rake push_message:tomorrow_plans のコマンドで実行出来ます。 rake taskの解説記事 まとめ 如何でしたでしょうか? 実用的なアプリを作りたい場合プッシュメッセージは案外使うケースが多いと思うので、是非参考にして頂けると幸いです。Lineが提供しているgemを使用して書くことも出来ますがこのようなシンプルにpostするだけなので短い処理であれば使う必要はないと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

migrateしてしまったモデルとテーブルの削除方法

はじめに モデルを作成してマイグレーションしてから、作成されたモデルとテーブルを削除する必要があったので、その時の手順を残しておきます。 削除手順 ①モデル作成時のファイルを削除する。 ②削除用のファイルを新規作成する。 ③削除用のファイルに削除したいテーブルを記載。 ④マイグレーションして、削除を行う。 ①モデル作成時のファイルを削除する。 まず以下を入力して、該当モデル作成時のファイルを削除します。 今回は、クチコミサイト作成時商品にカテゴリを付与したいと考えたので、categoryモデルを作成して、categoriesテーブルが作成されていると仮定します。 rails destroy model category ②削除用のファイルを新規作成する。 次にテーブル削除するために新規でマイグレーションファイルを作成します。(GI上では削除できないため) 以下を記載します。 rails generate migration 任意のファイル名 ファイル名は後に削除するので何でも構いません。 ここでは、「delete_category_table」としておきます。 ③削除用のファイルに削除したいテーブルを記載。 マイグレーションファイルを開いて、以下を記載します。 delete_category_table.rb class DeleteCategoryTable < ActiveRecord::Migration[5.2] def change drop_table :categories  ←drop_table :削除したいテーブルを記載 end end ④マイグレーションして、削除を行う。 最後はマイグレーションして、テーブルの削除を反映させます。 rails db:migrate 以上となります。 終わりに 当初はテキストエディタ上で右クリック→deleteで削除した気になっていました。 当然それではきちんと削除されている訳なく…。 しっかりと根本から削除する必要があるのだなと学びました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】WIndows環境でrails db:resetしたとき、Couldn't drop database 'db/development.sqlite3'のエラーの対処法

症状 Windows環境でrails db:resetしたとき、下記エラーが表示されてしまいました。 マイグレーションファイルを更新して、データベースにあるテーブルの内容を更新したく、rails db:resetを実行しました。 ターミナル rails db:reset Permission denied @ apply2files - C:/Users/ユーザー名/environment/sampleApp/db/development.sqlite3 Couldn't drop database 'db/development.sqlite3' rails aborted! Errno::EACCES: Permission denied @ apply2files - C:/Users/ユーザー名/environment/sampleApp/db/development.sqlite3 bin/rails:4:in `<main>' Tasks: TOP => db:drop:_unsafe (See full trace by running task with --trace) 以下のコマンドで検索すると、どうやらRails自体のバグがあるようで、Windows環境で特定のコマンドを実行しようとすると、上記のようなエラーが発生するようです。 該当コマンドは以下です。 対象コマンド rails db:drop rails db:reset rails db:migrate:reset 今回はrails db:resetが該当します。 解決方法 railsのdbのフォルダに移動し、手動でデータベースを削除する必要があるとのこと。 実際にやってみると、正常にデータベースが削除できました。 del development.sqlite3 migrationファイルを編集し、下記コマンドを実行すると正常にテーブルが更新できました。 rails db:migrate 参考 【Ruby on Rails】rails db:dropコマンドを実行したとき、エラーメッセージ「Couldn’t drop database ‘db/development.sqlite3’ rails aborted!」が表示されてしまう原因と解決策をお伝えします https://www.tairaengineer-note.com/rails-couldnt-drop-database/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

capistrano 踏み台サーバがある場合のconfig/deploy/production.rbの書き方

構成 -------------------- target_server user: deploy key: id_rsa.pemが必要 -------------------- ^ | -------------------- bastion_server.com user: bastion_user -------------------- ^ | -------------------- local -------------------- config/deploy/production.rb server "target_server", user: "deploy", roles: %w{app db web}, my_property: :my_value set :ssh_options, { keys: %w(~/.ssh/id_rsa.pem), forward_agent: false, user: 'deploy', proxy: Net::SSH::Proxy::Command::new('ssh bastion_user@bastion_server.com -W %h:%p') } 参考 config/deploy/production.rbの設定について https://gist.github.com/chansuke/737784de811f140853239daa7b6b75ef SSHのProxyCommandについて https://dev.classmethod.jp/articles/direct-ssh-by-proxycommand/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メモ】設定した環境変数を削除する

はじめに Railsでメール認証機能を実装した際、無駄に環境変数を設定してしまったためいらないものを削除したい。 削除方法 1 echoで設定されている値を確認 echo $PASSWORD 2 env, grepコマンドで設定されている値を表示 env | grep PASSWORD 3 unsetコマンドにより設定されていた値を削除 unset PASSWORD 4 env, grepコマンドで削除されていることを確認 env | grep PASSWORD 5 echoコマンドにより削除されていることを確認 echo $PASSWORD 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【メモ】環境変数について

はじめに Railsでメール認証機能を実装した際、無駄に環境変数を設定してしまったためいらないものを削除したい。 編集方法 vimで編集する。 vi ~/.bash_profile これを実行すると次の様に〜がたくさん出てくるので"i"を押して編集する。 export SECRET_KEY='secret' ~ ~ ~ ~ # "i"を押すとINSERTと表示される。 編集したらEscを押して、:wqと入力し終了する。 環境変数を適用させるには次の様に実行する。 source ~/.bash_profile これで環境変数が使える様になる。 ENV["SECRET_KEY"] 使える環境変数は次のコマンドで確認できる。 printenv 削除方法 1 echoで設定されている値を確認 echo $PASSWORD 2 env, grepコマンドで設定されている値を表示 env | grep PASSWORD 3 unsetコマンドにより設定されていた値を削除 unset PASSWORD 4 env, grepコマンドで削除されていることを確認 env | grep PASSWORD 5 echoコマンドにより削除されていることを確認 echo $PASSWORD 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails初学者によるRailsチュートリアル学習記録⑦ 第5章

目次 1. はじめに 2. 第5章の概要 3. 学習内容 4. 終わりに 1. はじめに この記事は、Rails初学者の工業大学三年生がRailsチュートリアルの学習記録をつけるための記事です。 筆者自体がRailsやWebについて知識が少ないので、内容の解釈などに間違いがある可能性があります。(その時はコメントで指摘してくださると助かります!) Railsチュートリアル内ではRailsの内容以外にも、gitでのバージョン管理やHerokuを使ったデプロイも学習しますが、gitに関しては既に私が学習済みのため学習記録には記述しません。 演習の記録も省略します。 2. 第5章の概要 この章ではBootstrapを使用して、サンプルアプリケーションにカスタムスタイルを組み込みます。 その途中でビューファイルなどの既存のファイルを扱いやすくなるような パーシャル、アセットパイプライン、名前付きルーティングを学んでいきます。 ただ、Bootstrapはフロント寄りの内容なので細かく記録はしません。 アセットパイプラインとは パーシャル パーシャルとは パーシャルでHTMLを分割する 名前付きルート 名前付きルートを使う準備 名前付きルートをルーティングに設定する 3. 学習内容 1. アセットパイプライン 1-1. アセットパイプラインとは アセットパイプラインとはCSS, JavaScript, ビューで使用する画像といったアプリケーション内の静的コンテンツを、 1つのファイルにまとめる仕組みのことです。 Railsアプリケーションの開発においてそれらのファイルはapp/assetsの下にある、 stylesheets, images, javascriptsといったディレクトリに保存します。 このように、ファイル自体は別々のディレクトリに保存されていますが、 アセットパイプラインによってそれらのファイルにアクセスするときは、 ファイル名のみでアクセスすることができます。 例えば、app/assets/images/ディレクトリに保存した画像をビューで表示させたいときは、以下のように書きます。 <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"), "https://rubyonrails.org/" %> image_tagというヘルパーを使用することで、Railsがapp/assets/images/ディレクトリ内からrails.svgという画像を探してくれます。 これによる主なメリットは本番環境でのユーザー体験にあります。 プログラマとしてはファイルの種類ごとにディレクトリが分かれていたほうが開発しやすいですが、 その分読み込み時間が長くなってしまいます。 この問題をアセットパイプラインは、分割されたファイルを結合し最小化するという方法で読み込み時間を短くして解決しています。 2. パーシャル 2-1. パーシャルとは RailsではHTMLヘッダーやHTML shim(IEに対応させるためのコード)といった1つのグループとして考えられるようなコードを、 それぞれのファイルに分割して、実際にそれを使用したいファイルで分割したファイルを呼び出すといった方法を取ることができます。 この方法によりビューの共通部分を記述したapplication.html.erbが以下のように書き換えられます。 ↓書き換え前 app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title><%= full_title(yield(:title)) %></title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> </head> <body> <header class="navbar navbar-fixed-top navbar-inverse"> <div class="container"> <%= link_to "sample app", '#', id: "logo" %> <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> </div> </header> <div class="container"> <%= yield %> </div> </body> </html> ↓書き換え後 app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title><%= full_title(yield(:title)) %></title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <%= render 'layouts/shim' %> <!-- パーシャル使用部分1 --> </head> <body> <%= render 'layouts/header' %>  <!-- パーシャル使用部分2 --> <div class="container"> <%= yield %> </div> </body> </html> 書き換え後のコードでは、コメントがある2箇所でパーシャルを使用しています。 1つ目は<%= render 'layouts/shim' %>という行で、IEに対応するための部分を別のファイルに移してそれを読み込んでいます。 読み込むときに使用しているヘルパーはrenderというヘルパーで、このヘルパーが実行されると app/views/layouts/_shim.html.erbというファイルを探してその内容を挿入します。 2つ目は<%= render 'layouts/header' %>という行で、ヘッダー部分を読み込んでいます、 このヘルパーではapp/views/layouts/_header.html.erbというファイルを探してその内容を挿入します。 2つの例から見て分かるように、パーシャルはファイル名の先頭にアンダーバーを入れる必要があります。 これによってRailsはパーシャルかどうかを識別しています。 2-1. パーシャルでHTMLを分割する 先述したコードはパーシャルを呼び出す側のコードです。 次は、分割されたパーシャルの内容を見ていきます。 ↓HTML shimのパーシャル app/views/layouts/_shim.html.erb <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> ↓headerのパーシャル app/views/layouts/_shim.html.erb <header class="navbar navbar-fixed-top navbar-inverse"> <div class="container"> <%= link_to "sample app", '#', id: "logo" %> <nav> <ul class="nav navbar-nav navbar-right"> <li><%= link_to "Home", '#' %></li> <li><%= link_to "Help", '#' %></li> <li><%= link_to "Log in", '#' %></li> </ul> </nav> </div> </header> 上記の二つのコードは元々application.html.erbに記述されていたコードです。 つまり、パーシャルを使用したいときは、アンダーバーが名前の初めについたファイルを app/views/layoutsの下に作成し、そこにコードをカット&ペーストして、元のファイルでrenderヘルパーを記述するだけで使用できます。 3. 名前付きルート 3-1. 名前付きルートとは 名前付きルートとはビューへのリンクなどを書くときに、 <a href="/static_pages/about">About</a> 上記のようにURLを直接記述するのではなく、 <%= link_to "About", about_path %> このabout_pathのようにリンク先を書くことができるようになるものです。 名前付きルートを使用することで、上記の例であればabout_pathの定義を変えることで about_pathが使用されているURLをすべて変更できるので、柔軟性が高まるといったメリットがあります。 3-2. 名前付きルートを使う方法 ここからは名前付きルートを使うための準備をしていきますが、 既に名前付きルートを使用した場面があります。 それがroot 'application#hello'というコードです。 これはルートURL("/")をhelloアクションに紐づけているコードで、これによりroot_pathとroot_urlといったメソッドが 使用できるようになっています。 上記のルーティングはルートURLの名前付きルートなので、それ以外のページを同じように書くことはできません。 例えばhelpページのルーティング get 'static_pages/help'を変更するときは、 get '/help', to: 'static_pages#help'と書きます。 これによりhelp_pathやhelp_urlといった名前付きルートが使用できるようになります。 ちなみにこの2つは返ってくる文字列が違います。 ・help_path → '/help' ・help_url → 'https://www.example.com/help' pathはルートURL以下の文字列、urlは完全なURLの文字列が返ってきます。 また上記の方法ではアクション名を使った名前付きルートになりますが、 全く違う名前を使用したいときはas:オプションを使用します。 as:オプションを使った書き方は以下の通りです。 get '/help', to: 'static_pages#help', as: 'herupu' このコードではhelpアクションをherupuという文字列を使って表しています。 よって、herupu_pathやherupu_urlが使用できるようになります。 4. 終わりに 第5章ではこれまでに作成した、ビューへのスタイルの適用を中心に学びました。 私の記事では、フロントエンドの内容より、バックエンドの内容を振り返りたいのでBootstrapやSassの内容でなく、 アセットパイプラインやパーシャルといったRailsの特長と言える部分について記録するようにしました。 前回の投稿から期間が空きましたが、第6章の内容まで進めた後にこの記事を書いているので次の記事はすぐに投稿する予定です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

awsでデプロイする【初心者】

スクールのデプロイ手順 卒業してからも使うために忘備録。ところどころ違うかも知れませんので注意です。 目次 1.VPCを作成する 2.サブネットを作成する 3.インターネットゲートウェイを作成する 4.ルートテーブルを作成する (1~4まではdefaultで作成させることも出来る) 5.EC2を作成する 6.RDSを作成する 7.EC2にログインして設定を行う 8.デプロイの自動化をする 9.SSLの導入 1,VPCを作成する VPCとは「Virtual Private Cloud」の略で、物理的な環境(リージョン)上に構築する仮想ネットワークのこと。 今から作るEC2達が使える住所はここだよ~って定義してあげるもの(多分) サービスからVPCを選択 VPCをクリックしたら、オレンジ色のボタンのVPCを作成をクリックする 名前タグ-オプション 任意で決める。私は分からなくなっちゃうので、「VPC-for-アプリケーション名」で作成 IPv4 CIDR ブロック 住所を決める。この住所はプライベートなIPアドレスで、ルールが決められている IPアドレス範囲 CIDR表記 0.0.0.0 ~ 10.255.255.255 10.0.0.0/8 172.16.0.0 ~ 172.31.255.255 172.16.0.0/12 192.168.0.0 ~ 192.168.255.255 192.168.0.0/16 「172.31.0.0/16」とか、「192.168.0.0/16」とか入力 VPCを作成をクリック 2,サブネットを作成する サブネットはVPCで設定した中に、さらに小さな仮想ネットワークを作成するAWSのサービス。用途に合わせて、必要な仮想ネットワークを作成する。 VPCが東京都だとしたら、サブネットは新宿区とか渋谷区とかそんな感じのイメージ(多分。違うけどイメージはそんな感じ) 左からVPCの下にあるサブネットをクリックし、右のサブネットを作成をクリック VPC ID 先ほど作ったVPCを選択する。 このVPCを間違ってしまうと、うまく接続出来ない (さっきの例で行くと東京都新宿区なのに北海道新宿区みたいになって、住所が無いよ!ってなってしまう(多分)) VPCを選択するとサブネットの設定が出てくる サブネット名 任意の名前を入力。私は分からなくなってしまうので、「public-subnet-1a-for-アプリケーション名」で作成 アベイラビリティーゾーン アジアパシフィック(東京)のap-northeast-1aを選択。 (どのアベイラビリティーゾーンでもいいけど、私はサブネット名が-1aの時は1aで-1cの時は1cで命名している。) IPv4 CIDR ブロック サブネットのCIDRは被ってはいけない。(エラーが出る) (東京都に新宿区が2つあってはいけないみたいな(多分)) さっき、「172.31.0.0/16」で入力していたら、「172.31.0.0/20」と入力 「192.168.0.0/16」で入力していたら、「192.168.0.0/20」と入力。 サブネットを作成をクリック え?????被って無いの??????って私は最初なったので、後で解説を書いておこうかなと思う。 3,ゲートウェイを作成する 左のタブのルートテーブルを一つ飛ばして、ゲートウェイを作成する。 ゲートウェイは名の通りgate。インターネットと接続できるためのゲートを用意するもの。 左のタブのインターネットゲートウェイをクリックし、右上のインターネットゲートウェイの作成をクリックする 名前タグ 任意の名前を決める。私は分からなくなってしまうので「gateway-for-アプリケーション名」を入力 インターネットゲートウェイの作成をクリック 作成されましたみたいな画面になったら、VPCへアタッチをクリック 先ほど作成したVPCを選択して、インターネットゲートウェイのアタッチをクリック。 状態がAttachedだったらOK 4,ルートテーブルを作成する 「ルートテーブル」はAWS上の仮想的なネットワーク環境のことで、サブネット内のAWSリソース(EC2インスタンスなど)がどこに通信しにいくのかのルールを定めます。 ゲートウェイという門を作っても、道路が無いとインターネットを行き来できないので、ルートテーブルを作成するという感じ。 左のタブのルートテーブルをクリックし、今度は青いボタンのルートテーブルの作成をクリックする。 名前タグ 任意の名前を入力。私は分からなくなってしまうので、「public-route-table-for-アプリケーション名」と入力 VPC 先ほど作成したVPCを選択する 作成をクリック 次にルートテーブルとサブネットを紐づける。先ほど作成したルートテーブルのサブネットの関連付けのタブをクリック サブネットの関連付けの編集をクリック 先ほど作成したサブネットを選択し、保存 次にルートタブをクリックし、ルートの編集をクリック 今はローカルだけになっているので、ルートの追加をクリック。 送信先 0.0.0.0/0を入力 ターゲット 選択タブの Internet Gatewayを選択後、先ほど作成したゲートウェイが出てくるので、クリック 出てこなかったら、上の設定のどこかが違う可能性あり。 無事出てきたら、ルートの保存をクリック インターネットに接続するための住所と道路の確保が出来た状態になりました。 結構書くの時間かかった!EC2からは明日書きます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsの設計思想「CoC」について

はじめに まずRailsには設計思想として3つ強く打ち出しています。 1. CoC (Convention over Configuration) 2. DRY (Don’t Repeat Yourself) 3. REST(Representational State Transfer) 今回は1のCoCについて解説したいと思います。 CoCとは 直訳すると「設定より規約」という意味になります。例えばユーザー情報を表現するモデルをUserモデルとした場合、Railsでは以下の様なルールに則って開発します。 データベースのモデル名の複数形にする(Users) /usersというURLは社員の一覧を表す ユーザーID:1のユーザー情報を表すURLは/users/1になる 上記の様なルールで書くとそれぞれに細かく設定を紐付ける作業を省略できます。 「便利ですね〜」 またこれらの規約に従うとプログラム内に規律が生まれ以下の様な、メリットもあります。 多くの設定ファイルを書かなくて良い 共通のルールがあることで他のエンジニアとスムーズなコミュニケーションが取れる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】Userモデルに後からDeviseを入れたらログインできなくなった事件

起こった問題 Webサービスを作ろうとUserモデルを作成。 とりあえずRailsチュートリアルに倣って進めるも、Deviseが使いたくなったので途中で方針転換。 メール認証機能を作ったところでDeviseを導入、作り直すことに。 ユーザーの作成はできた(?)がどうもログインができず。 (エラーは出ないが「メールアドレスまたはパスワードが正しくない」と言われる。) ※もちろん正しいものでトライしてます。 結論 UserモデルにRailsチュートリアル内で作った名残が残っていたせいで不具合が起き、 encrypted_passwordにパスワードが保存されなかったことが原因でした。 user.rb class User < ApplicationRecord (以下抜粋) attr_accessor :remember_token, :activation_token, :activation_digest, :password_digest #←ここ消す has_secure_password #←ここ消す Deviseでいいようにやってくれるのでhas_secure_passwordとpassword_digest属性は不用。消しましょう。ということでした。 残してると色々メソッド名やらなんやらがバッティングしちゃってうまくいきません。 潔く思い出はさよならしましょう。 解決に至った経緯 とりあえずブラウザで作ったユーザーをコンソールで見てみる。 #ブラウザから作ったユーザーを取得 user = User.last user.valid? => false user.encrypted_password => "" user.valid?がfalse。 user.encrypted_passwordが""。 あれ、パスワード保存されてなくない? 疑惑① フォームからパスワードの送信or保存が上手くいってない? であれば、コンソール上でユーザーを作成してみる。 user2 = User.new(name: "Test Taro", email: "test@example.com", password: "password", password_confirmation: "password") user2.valid? => true user2.valid?がtrueになったのでログインいけるかな?と思いきや やはりアドレスかパスワードが違うと言われログインできない。 コンソールで見てみると user2.encrypted_password => "" user2.password => "password" やっぱりencrypted_passwordが保存されてない。 一応、userのpassword属性には値が入っている。 であればフォームのせいではなさそう。(自動生成されたものからいじってないし) 疑惑② もともと作っていたパスワード周りの何やかんやが悪さしているな。 一旦models/user.rbを見返す。いらないものは消していこう。 has_secure_password不要! →消す →ログインを試みる →エラー発生 ArgumentError in Devise::SessionsController#create wrong number of arguments (given 1, expected 0) Extracted source (around line #67): def password=(new_password) @password = new_password self.encrypted_password = password_digest(@password) if @password.present? #ここに赤線入ってる end # Verifies whether a password (ie from sign in) is the user password. 引数いらないのに1個渡しちゃってるらしい。 何か思い当たる節は・・・ ん、password_digestという聞き覚えのある単語・・!!! attr_accessorに:password_digestが残ってたので消す →解決!!!! 参考 【Rails】devise実装後のユーザー新規登録時のエラー[ArgumentError in Users::RegistrationsController#create]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラーメッセージの日本語翻訳(実装からエラー解決まで)

はじめに アプリケーションで英語エラーメッセージを日本語化する実装を行なったため、その過程及び実装中で起こったエラーとその解決を記録として残します。 条件 Ruby: 2.6.5 Rails: 6.0.3.6 Git: 2.30.1 Unicorn: 5.4.1 目次 事前準備 エラーメッセージの日本語訳 本番環境に反映 エラーとその解決 おわり 1. 事前準備 viewの編集 まずは、エラーメッセージ専用のviewを作成。 複数のviewで使用することを想定されているものは、別で切り出して用意しておき、呼び出すだけでいいように準備しておきます。 今回は、views / shared に_error_messages.html.erbファイルを自作しました。 views └ shared └ _error_messages.html.erb _error_messages.html.erbファイルの中身 app/views/shared/_error_messages.html.erb <% if model.errors.any? %> <div class="error-alert"> <ul> <% model.errors.full_messages.each do |message| %> <li class='error-message'><%= message %></li> <% end %> </ul> </div> <% end %> model.errors.any?を記述することで、どのモデルのバリデーションにも対応できるようにします。 次に、このエラーメッセージを表示さたいviewに呼び出します。 エラーメッセージの呼び出し renderを用いてエラーメッセージを表示させたい部分に、以下のように記述する。 記述例 <%= form_with model: @purchase_address, url: item_purchases_path, id: 'charge-form', class: 'transaction-form-wrap',local: true do |f| %> <%# エラーメッセージの呼び出し %> <%= render 'shared/error_messages', model: f.object %> <div class='credit-card-form'> <h1 class='info-input-haedline'> クレジットカード情報入力 </h1> <%# 以下省略 %> これで、エラーメッセージの表示が完了。 2. エラーメッセージの日本語訳 日本語化の設定 config / application.rb 内を以下のように編集。 config/application.rb module アプリケーション名 class Application < Rails::Application config.load_defaults 6.0 # 日本語の言語設定 config.i18n.default_locale = :ja end end 続いて、Gemfileにrails-i18nというGemを導入 → ターミナルで、bundle install Gemfile gem 'rails-i18n' ターミナル bundle install ※ application.rb内に日本語の設定の記述をしていないと、Gemを導入してもに日本語で設定されないため、必ず記述。 現段階ではまだ、ログイン / 新規登録と一部エラーメッセージが英語であるため以下の作業で完全に日本語化していく。 localeファイル 色々な言語に対応できる言語ファイル。 ファイルは、YAMLというファイル形式で記述する。 config / localesディレクトリに、devise.ja.ymlファイルを作成。 config └ locales └ devise.ja.yml devise.ja.ymlファイルには、下記のサイトより記述内容を拝借して貼り付けする。 devise-i18n/ja.yml config/locales/devise.ja.yml ja: activerecord: attributes: user: confirmation_sent_at: パスワード確認送信時刻 confirmation_token: パスワード確認用トークン confirmed_at: パスワード確認時刻 created_at: 作成日 current_password: 現在のパスワード current_sign_in_at: 現在のログイン時刻 current_sign_in_ip: 現在のログインIPアドレス email: Eメール encrypted_password: 暗号化パスワード failed_attempts: 失敗したログイン試行回数 last_sign_in_at: 最終ログイン時刻 last_sign_in_ip: 最終ログインIPアドレス locked_at: ロック時刻 password: パスワード # 以下略 ※ インデントにミスがあるとエラーを起こすため、よく確認しておく。 これで、ログイン / 新規登録のエラーメッセージの日本語化は完了。 しかしまだ一部英語が残るため、最後は手動で日本語化していく。 ja.ymlファイルを作成 config / localesディレクトリに、ja.ymlファイルを作成。 config └ locales ├ devise.ja.yml └ ja.yml インデントに気をつけて日本語化したい部分を記述していく。 config/locales/ja.yml ja: activerecord: attributes: user: nickname: ニックネーム item: name: 商品名 description: 商品の説明 # ~ 中略 ~ # ActiveModelの場合 activemodel: attributes: purchase_address: postcode: 郵便番号 region_id: 都道府県 city: 市区町村 block: 番地 phone_number: 電話番号 token: クレジット情報 テストコードを書いている場合 エラーメッセージを日本語化したため、テストコードのエラー文も英語から日本語に変換しておく。 context '新規登録ができない時' do it 'nicknameが空では登録できない' do @user.nickname = '' @user.valid? expect(@user.errors.full_messages).to include('ニックネームを入力してください') end it 'emailが空では登録できない' do @user.email = '' @user.valid? expect(@user.errors.full_messages).to include('Eメールを入力してください') end it '重複したemailは登録できない' do @user.save another_user = FactoryBot.build(:user, email: @user.email) another_user.email = @user.email another_user.valid? expect(another_user.errors.full_messages).to include('Eメールはすでに存在します') end 3. 本番環境に反映 以下の記述は、自動デプロイの実装を行なっている程で話をしています。 変更内容はリモートリポジトリにcommitしてpushしておく。 (ブランチを切っていたら、mergeまで実行) ターミナル(EC2内) ① pemファイルがあるディレクトリに移動 % cd .ssh ② EC2にログイン .ssh % ssh -i <鍵の名前>.pem ec2-user@ <Elastic IP> ③ 開発中のアプリケーションのディレクトリに移動 [ec2-user@ip-111-22-33-444 ~]$ cd /var/www/開発中のアプリケーション名 ⑤ GitHubからEC2へ反映 [ec2-user@ip-111-22-33-444 リポジトリ名]$ git pull origin master ④ 現在動いているプロセスの確認 [ec2-user@ip-111-22-33-444 リポジトリ名]$ ps aux | grep unicorn ec2-user 18365 0.1 12.2 483188 123304 ? Sl 05:11 0:01 unicorn master -c ..... ec2-user 18406 0.0 12.2 489520 123072 ? Sl 05:11 0:00 unicorn worker[0] -c ..... ec2-user 18704 0.0 0.0 119436 964 pts/0 S+ 05:25 0:00 grep --color=auto unicorn ⑤ 'unicorn master'のプロセスID(左から2番目の番号)をkillする [ec2-user@ip-111-22-33-444 リポジトリ名]$ kill 18365(上記の場合) ターミナル(ローカル) ⑥ サーバー再起動 % bundle exec cap production deploy 4. エラーとその解決 本番環境にデプロイした時に実際に起こったエラーと解決までの作業を記述します。 本番環境で「新規登録」ページに遷移するとエラー ①エラーログの確認 ターミナル ① logディレクトリに移動 [ec2-user@ip-111-22-33-444 リポジトリ名]$ cd log ② ls でlogディレクトリの中身を確認 [ec2-user@ip-111-22-33-444 log]$ ls production.log unicorn.stderr.log unicorn.stdout.log ③ production.log でログの確認('tail -f'でログの10行分を表示) [ec2-user@ip-111-22-33-444 log]$ tail -f production.log 実際にエラーがあった時の表示 怪しいのは、一番上のこの部分。 ターミナル [ee4c13d3-......] ActionView::Template::Error (undefind method `map' fo "translation missing: ja.data.order":String): translation missing: ja.data.ordeということから、日本語訳がうまくいっていないんじゃないか...?と考えられる。 【解決】 プロセスを停止(kill)した上で、再起動を行うと反映された。 プロセス停止 → サーバー再起動の手順が上手くいっていなかった...? 本番環境のディレクトリに日本語翻訳したファイルがない 本番環境のディレクトリに日本語訳するためのファイル(devise.ja.yml・ja.yml)があるか確認(config / locales の中を確認)。 ターミナル ① ls でconfigがあるか確認 [ec2-user@ip-111-22-33-444 リポジトリ名]$ ls Capfile README.md babel.config.js config.ru furima.dio node_modules public revisions.log storage vendor Gemfile Rakefile bin current lib package.json releases shared test yarn.lock Gemfile.lock app config db log postcss.config.js repo spec tmp ② configディレクトリに移動 [ec2-user@ip-111-22-33-444 リポジトリ名]$ cd config ③ config内のディレクトリを確認 [ec2-user@ip-111-22-33-444 config]$ ls application.rb cable.yml database.yml deploy.rb environments locales routes.rb storage.yml webpack boot.rb credentials.yml.enc deploy environment.rb initializers puma.rb spring.rb unicorn.rb webpacker.yml ④ localesディレクトリに移動 [ec2-user@ip-111-22-33-444 config]$ cd locales ⑤ localesの中身を確認 [ec2-user@ip-111-22-33-444 locales]$ ls devise.en.yml en.yml 長々と書きましたが、これは1つずつ確実に中身を確認するために記述したため、本来は以下の記述でlocalesディレクトリまで移動できます。 ターミナル [ec2-user@ip-111-22-33-444 リポジトリ名]$ cd config/locales [ec2-user@ip-111-22-33-444 locales]$ ls devise.en.yml en.yml localesの中みを見ると、日本語訳にするためのファイル(devise.ja.yml・ja.yml)が見当たらない。 【原因】 コードの変更を、commit → push(もしくはmerge)した時点で満足し、GitHubからEC2へ反映していなかった。 git push origin master のし忘れ。 【解決】 ターミナルでEC2へ変更を反映。 ターミナル [ec2-user@ip-111-22-33-444 リポジトリ名]$ git pull origin master 5. おわり 本番環境に反映されない時は、以下の確認を行う。 変更・追加をリモートリポジトリにcommit→push(またはmerge)しているか GitHubからEC2へ(git pull origin master)したか EC2インスタンスの再起動 エラーログの確認
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsに読み込まれているgemのversion確認方法

Gem.loaded_specs["<library-name>"].version => Gem::Version.new("3.54.2")
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]herokuで画像の保存場所にAmazonS3を使用してみる

はじめに 本記事ではAWSの設定等は含まれておりません。あらかじめご了承ください AmazonS3とは S3とは、AWSが提供するサービスの一つで、インターネット上にデータを保存する箱を借りられるサービスというものです。 S3を利用することで、画像を保存したり、保存してある画像を取得したりすることができます。 実装方法 まずは画像投稿した際などに画像の保存先がS3となるように変更していきます。 はじめにS3が使用できるようにしましょう。 #一番下に記述 gem "aws-sdk-s3", require: false ※bundle installを忘れずに!! 続いて、画像の保存先を指定します。 config/environments/development.rb # ~省略~ #config.active_storage.service = :local #コメントアウト!!!!! config.active_storage.service = :amazon # ~省略~ 次に、S3で使用するバケット名とリージョン名を記述します。 config.storage.yml test: service: Disk root: <%= Rails.root.join("tmp/storage") %> local: service: Disk root: <%= Rails.root.join("storage") %> #以下を追記 amazon: service: S3 region: ap-northeast-1 bucket: ご自身の「バケット名」を入力 #ここまで # ~省略~ 次に、S3にアクセスするための認証情報を設定します。 これは機密情報なので環境変数にいれます。 % vim ~/.zshrc 以下を記述してください export AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け" export AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け" なお、ここにいれるものは、AWSでIAMユーザを作った際にダウンロードする「new_user_credentials.csv」に記載してあります。 入力したら保存して(esc+:wq)してパスを通します % source ~/.zshrc ここまでで、環境変数を設定することができました。 実際にソースコード内で環境変数を使用して、S3への認証情報を記述しましょう。 config/storage.yml #省略 amazon: service: S3 region: ap-northeast-1 bucket: (自身のバケット名が記載されている状態です) #追加 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> # ~省略~ ここまででローカル環境では保存先がS3になっているかと思います。何かを投稿した時、AWS側で確認することができるかと思います。 さあ!後少し!! ローカル同様に、heroku上でも環境変数を設定します。Herokuで環境変数を扱うには、「heroku config:setコマンド」を打つ必要があります。 % heroku config:set AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け" % heroku config:set AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け" 反映されたかどうかは、以下のコマンドで確認できます % heroku config あ!!!忘れてた、、、 本番環境でも保存先を変更しておきましょう config/environments/production.rb # ~省略~ #config.active_storage.service = :local #コメントアウト config.active_storage.service = :amazon # ~省略~ あとは、これらの変更点をherokuに反映っと、、、 % git push heroku master 完成!!!! #補足(エラー発生した人向け) 画像の保存先の設定を変更することにより、画像の参照先がアプリケーション内からS3へ置き換わります。 当然、S3導入前に投稿した画像が表示できなくなります。 それが嫌だ!!という方や何かしらのエラーが出た方は以下のコマンドを実行し、一度データベースをリセットしてください。 この際、データベースに保存されていたデータは全て消えるため注意しましょう。 % heroku run DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rails db:drop db:create db:migrate おわりに 前回の記事と合わせれば、ひとまずherokuでのデプロイは完璧にできるかと思います。 次はCircleCIやDocker、AWSの導入に挑戦していきます!!! 前回の記事([Rails]ノーエラーでherokuへデプロイしていく) https://qiita.com/tochisuke221/items/62d114989e872fa4e50a
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【rails6】結合テストエラーの解決 `it` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block).

こんにちは! 今日も結合テストで犯した凡ミスについて共有していこうと思います 凡ミスばかりですみません… でもこういった凡ミスで無駄な時間を過ごしてしまう方々が一人でも減ればなぁと信じて 是非読んでいってください! では、まずは今日のエラーをご紹介 発生したエラー % bundle exec rspec spec/system/comments_spec.rb # この結合テストを実行した際に Failure/Error: it 'ログインしたユーザーはコメントできる(自分の投稿にコメントする場合)' do # 省略 `it` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block). # ↑このエラーが発生しました↑ さて、このエラー文 `it` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block). を日本語訳してみましょう it` は、サンプル内(例:`it` ブロック)や、サンプルのスコープ内で実行されるコンストラクト(例:`before`、`let` など)からは利用できません。サンプルグループ(例:`describe`や`context`ブロック)でのみ利用可能です。 みなさん英文を見た瞬間に「うわっ…」となるかもしれませんが、ここは慣れましょう 便利な翻訳サイトのリンクは下に貼りますが、できる限りご自身で読み解くことをお勧めします ※今はQiita投稿の為翻訳してます では、原因となるコードを見てみましょう comments_spec.rb it '空欄のコメント送信はできない' do it 'ログインしたユーザーでも空欄コメントは送信できない' do # ログインし、root_pathにいることを確認する sign_in(@article1.user) expect(current_path).to eq root_path expect(page).to have_no_content('ログイン') # @article1の詳細ページに遷移する visit article_path(@article1) expect(page).to have_content(@article1.title) # コメント欄があることを確認、フォームに入力する expect(page).to have_selector(".send-comment-text") fill_in "コメントを入力", with: '' # コメントを送信しても、Commentモデルのカウントが上がらない事を確認する expect{find('input[name="commit"]').click}.to change { Comment.count }.by(0) # コメントがページこのページ内に存在していないか確認する expect(page).to have_no_content(@comment) end end 何がいけないか、もうお分かりですよね?? itの中にitを書いてしまっている!! という事です 「別のテストコードをコピペ活用する中で、不要なit文を削除し忘れた」ということですね では、解決していきましょう comments_spec.rb it 'ログインしたユーザーでも空欄コメントは送信できない' do # ログインし、root_pathにいることを確認する sign_in(@article1.user) expect(current_path).to eq root_path expect(page).to have_no_content('ログイン') # @article1の詳細ページに遷移する visit article_path(@article1) expect(page).to have_content(@article1.title) # コメント欄があることを確認、フォームに入力する expect(page).to have_selector(".send-comment-text") fill_in "コメントを入力", with: '' # コメントを送信しても、Commentモデルのカウントが上がらない事を確認する expect{find('input[name="commit"]').click}.to change { Comment.count }.by(0) # コメントがページこのページ内に存在していないか確認する expect(page).to have_no_content(@comment) end これだけです。上記との違いは、重複されていたit文を片方削除しました。 ターミナルで実行します % bundle exec rspec spec/system/comments_spec.rb Comments コメントできるとき ログインしたユーザーはコメントできる(自分の投稿にコメントする場合) ログインしたユーザーはコメントできる(他人の投稿(@article2)にコメントする場合) コメントできないとき ログインしていないユーザーはコメントできない 空欄のコメント送信はできない Finished in 20.88 seconds (files took 1.77 seconds to load) 4 examples, 0 failures うん、OKです!! では、下記ご参考まで… 便利な翻訳サイト DeepL様 https://www.deepl.com/translator
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

while

while 条件によって繰り返し処理を行う場合はwhileを使用しましょう。 以下のように使用します。 while 条件式 do 処理するアクション end もしプログラムを終了させず同じ処理を繰り返すループ処理を行う場合は、以下のようにします。 while true do 処理するアクション end 上記の書き方だと無限ループするので、任意のタイミングで中断させたい場合はctrl+cを押します。 (問)以下の仕様を満たすアプリケーションを作成します。 「仕様」:プログラムの実行すると、 ①「[0]:カロリーを表示する、[1]:終了する」という選択肢が表示され、数字を入力することができる ② 0を入力すると「500kcal」と表示され、上記条件①が繰り返し実行される。 ③ 1を入力するとアプリケーションが終了する 解答例 while true do puts "[0]:カロリーを表示する" puts "[1]:終了する" input = gets.to_i if input == 0 puts "500kcal" elsif input == 1 exit end end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

module

モジュール モジュールとは、Rubyにおける「インスタンスを生成できないクラス」のようなもののことです。 下記のように定義します。 module モジュール名 end また、モジュールの中にはクラスを定義することもできます。 module Sample class Test end end この「Testクラス」は下記のようにして呼び出すことができます。 Sample::Test クラスとモジュールの使い分けとして、具体的なオブジェクトを生成したい場合(インスタンスを生成したい場合)はクラスを使用し、処理だけ(メソッドなど)が必要な場合はモジュールを使用します。 またモジュールの中にクラスを定義するメリットは、Testクラスが複数ある場合に、下記のような記述でクラスごとに区別ができます。 module Sample1 class Test end end module Sample2 class Test end end Sample1::Test Sample2::Test こうすることで、同じクラス名でも定義することができ、それぞれ区別して使用することができます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

継承の仕組み

継承の仕組み あるクラスを継承して新しいクラスを作る場合には以下のように「新しいクラス < 元となるクラス」と書きます。 【例】sample.rb class PoliceCar < Car end クラスを継承すると、親クラスから子クラスへ以下のものが引き継がれます。 親のインスタンス変数 親のインスタンスメソッド 例えば、Carクラスを継承したPoliceCarクラスを作成するコードを以下に示します。 【例】sample.rb class Car def initialize(car_type, capacity) @name = car_type @capacity = capacity end def info puts "車種:#{@name} 乗車定員:#{@capacity}人" end end class PoliceCar < Car end police_car = PoliceCar.new("パトカー", 5) police_car.info # ターミナル出力結果 # 車種:パトカー 乗車定員:5人 上記を見てみると、PoliceCarクラスの中には何も記述をしていませんが、継承元のCarクラスのインスタンス変数およびインスタンスメソッドを使うことができます。 インスタンスメソッドを追加する方法 続いて子クラスに独自のインスタンスメソッドを追加する方法について 子クラス内に新しくメソッドの定義を追加するだけです。 先ほどのPoliceCarクラスを例に説明をします。以下を見てください。 br【例】sample.rb class Car def initialize(car_type, capacity) @name = car_type @capacity = capacity end def info puts "車種:#{@name} 乗車定員:#{@capacity}人" end end class PoliceCar < Car def siren puts "ウゥ〜ウゥ〜" end end police_car = PoliceCar.new("パトカー", 5) police_car.siren # ターミナル出力結果 # ウゥ〜ウゥ〜 上記では、PoliceCarクラス内にsirenメソッドを新たに追加し、それを実行しています。 このように子クラスにインスタンスメソッドを追加することで、そのクラス固有のメソッドを定義することができます。 メソッドを上書きする方法 最後にメソッドを上書きする方法について.親クラスにあるメソッドと同じ名前のメソッドを子クラスで定義すると、メソッドを上書きすることができます。これをメソッドの「オーバーライド」と呼びます。 オーバーライド オーバーライドとは、親クラスのメソッドを子クラスに同名のメソッドを定義することによって上書きすることを指します。 【例】sample.rb class Car def initialize(car_type, capacity) @name = car_type @capacity = capacity end def info puts "車種:#{@name} 乗車定員:#{@capacity}人" end end class PoliceCar < Car def info puts "車種:#{@name} 乗車定員:#{@capacity}人 パトロール時間:24時間" end def siren puts "ウゥ〜ウゥ〜" end end police_car = PoliceCar.new("パトカー", 5) police_car.info # ターミナル出力結果 # 車種:パトカー 乗車定員:5人 パトロール時間:24時間 上記では、Carクラスで定義されたinfoメソッドと同名のメソッドをPoliceCarクラス内で定義しています。 これによって、PoliceCarクラスを元に生成されたインスタンスでinfoメソッドを実行すると、上書きされた処理が実行されるようになります。 問問題.1 以下の仕様にしたがってコードを記述してください。 ・Personクラスはプロパティ name, ageを持っている。 ・StudentクラスはPersonクラスを継承している。 ・Studentクラスにはintroduceメソッドが定義されている。実行すると  「私の名前は◯◯です。◯歳です」と表示がされる。 ・Studentクラスのインスタンスを作成し、introduceメソッドを実行する。 【例】 class Animal def initialize(name) @name = name end end class Dog < Animal def name puts "名前は#{@name}です。" end end pochi = Dog.new("ポチ") pochi.name class Person def initialize(name,age) @name = name @age = age end end class Student < Person def introduce puts "私の名前は#{@name}です。#{@age}才です。" end end taro = Student.new("Taro",13) taro.introduce
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails Dockerfile docker-compose を別pjから移したときにGemfile.lockが原因で起動しなかった

docker-compose.yml、Dockerfileなどを別プロジェクトから移行してきたときに以下のようなエラーが出て起動できなかった。メモ用に エラー $ docker-compose up --build を実行したときに以下のようなエラーが出た app_1 | Bundler::GemNotFound: Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile. app_1 | /usr/local/lib/ruby/2.6.0/bundler/resolver.rb:287:in `block in verify_gemfile_dependencies_are_found!' app_1 | /usr/local/lib/ruby/2.6.0/bundler/resolver.rb:255:in `each' app_1 | /usr/local/lib/ruby/2.6.0/bundler/resolver.rb:255:in `verify_gemfile_dependencies_are_found!' app_1 | /usr/local/lib/ruby/2.6.0/bundler/resolver.rb:49:in `start' app_1 | /usr/local/lib/ruby/2.6.0/bundler/resolver.rb:22:in `resolve' app_1 | /usr/local/lib/ruby/2.6.0/bundler/definition.rb:258:in `resolve' app_1 | /usr/local/lib/ruby/2.6.0/bundler/definition.rb:170:in `specs' app_1 | /usr/local/lib/ruby/2.6.0/bundler/definition.rb:237:in `specs_for' app_1 | /usr/local/lib/ruby/2.6.0/bundler/definition.rb:226:in `requested_specs' app_1 | /usr/local/lib/ruby/2.6.0/bundler/runtime.rb:108:in `block in definition_method' app_1 | /usr/local/lib/ruby/2.6.0/bundler/runtime.rb:20:in `setup' app_1 | /usr/local/lib/ruby/2.6.0/bundler.rb:107:in `setup' app_1 | /usr/local/lib/ruby/2.6.0/bundler/setup.rb:20:in `<top (required)>' app_1 | /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' app_1 | /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' app_1 | bundler: failed to load command: puma (/webapp/vendor/bundle/ruby/2.6.0/bin/puma) 解決 Gemfile.lockの中身を削除して再度 docker-compose up --buildを再度実行。 必要に応じてコンテナ内でbundle installを実行する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6】deviseで独自カラムを追加して使用する方法 ①

はじめに Railsのログイン認証で、deviseを使用する機会が多いかと思いますが、独自のカラムを追加して使用する方法をご紹介します。 今回のテーマは、独自カラムの追加とログイン時に独自のカラムで行えるようにすることにします。 環境 MacOS : Big Sur Ruby : 3.0.1 Rails : 6.1.3.1 ① gem devise 追加 Gemfile に追記していきます。 Gemfile gem 'devise' bundle install コマンドの実行 bundle install ② devise インストール deviseをインストールする rails g devise:install コマンドを実行 rails g devise:install Running via Spring preloader in process 4466 create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Depending on your application's configuration some manual setup may be required: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. * Required for all applications. * 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" * Not required for API-only Applications * 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> * Not required for API-only Applications * 4. You can copy Devise views (for customization) to your app by running: rails g devise:views * Not required * =============================================================================== ③ Userモデル 作成 Userモデルを追加する rails g devise user コマンドを実行 rails g devise user Running via Spring preloader in process 4487 invoke active_record create db/migrate/20210505〇〇〇〇〇〇_devise_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml insert app/models/user.rb route devise_for :users 上記コマンドを実行すると、DeviseのUserモデルが作成されるので、作成されるマイグレーションファイルを編集し独自カラムを追加します。 ④ マイグレーションファイル 編集 /db/migrate/20210505〇〇〇〇〇〇_devise_create_users.rb ファイルを編集していきます。 ※ 生成されたマイグレーションファイルで、一部コメントアウト # t.string されているので、必要に応じて # を外します。 20210505〇〇〇〇〇〇_devise_create_users.rb_編集前 # frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[6.1] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable # t.integer :sign_in_count, default: 0, null: false # t.datetime :current_sign_in_at # t.datetime :last_sign_in_at # t.string :current_sign_in_ip # t.string :last_sign_in_ip ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## Lockable # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true # add_index :users, :confirmation_token, unique: true # add_index :users, :unlock_token, unique: true end end 20210505〇〇〇〇〇〇_devise_create_users.rb_編集後 # frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[6.1] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" #今回追加 t.string :user_code, null: false, default: "" #ユーザコード (ログインにも使用) t.string :user_last_name, null: false, default: "" #姓 t.string :user_first_name, null: false, default: "" #名 t.string :user_status, null: false, default: "enable" #ステータス ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable t.integer :sign_in_count, default: 0, null: false t.datetime :current_sign_in_at t.datetime :last_sign_in_at t.string :current_sign_in_ip t.string :last_sign_in_ip ## Confirmable t.string :confirmation_token t.datetime :confirmed_at t.datetime :confirmation_sent_at t.string :unconfirmed_email # メール認証をする場合 ## Lockable t.integer :failed_attempts, default: 0, null: false # ロック機能を利用する場合 t.string :unlock_token # ロック解除をメール等で行う場合 t.datetime :locked_at t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true add_index :users, :confirmation_token, unique: true add_index :users, :unlock_token, unique: true #今回追加 add_index :users, :user_code, unique: true end end 上記のように、コメントアウト・追加したいカラムを追加していきます。 ※ 今回は、初めの段階で、予定している使用機能のコメントアウト・追加したいカラムを追記しています。 マイグレーションした後でも、機能・カラムの追加は行えます。 ⑤ マイグレーション 実行 マイグレーションを行う rails db:migrate コマンドを実行 rails db:migrate == 20210505〇〇〇〇〇〇 DeviseCreateUsers: migrating ================================ -- create_table(:users) -> 0.0041s -- add_index(:users, :email, {:unique=>true}) -> 0.0016s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0014s -- add_index(:users, :confirmation_token, {:unique=>true}) -> 0.0016s -- add_index(:users, :unlock_token, {:unique=>true}) -> 0.0012s -- add_index(:users, :user_code, {:unique=>true}) -> 0.0015s == 20210505〇〇〇〇〇〇 DeviseCreateUsers: migrated (0.0134s) ======================= ここまで行うと、ログイン機能が使用できるようになりますが、 今回は、独自カラムを追加しているので、ビューやコントローラをカスタマイズする必要があります。 長くなりましたので、記事を分けてご紹介しようと思います。 次回は、ビューのカスタマイズを行っていきたいと思います。 ▽次の記事はこちら▽ 【Rails6】deviseで独自カラムを追加して使用する方法 ② ~ 申し訳ございません。公開までしばらくお待ちください。 ~
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む