- 投稿日:2021-03-25T23:11:24+09:00
【Rails】credentials.yml を使って管理画面を作る(その2)
■ はじめに
皆さん、こんにちは。
桜も開花して、春の訪れを見た目でも感じられるようになってきましたね。春の訪れを感じると共に、
年が開けてから随分と時間が経ってしまったのだなと、
やや焦りを感じてしまう自分がいるのですが、皆さんはどうでしょうか?今回は前回の「【Rails】credentials.yml を使って管理画面を作る(その1)」の続きになります。(前回⇒ https://qiita.com/tsuchiya-yu2/items/ab77a59abb9aef73f187 )
今回は前回以上に作業がありますので、焦らずゆっくり進めていきましょう!
(Qiitaの表示ではコードが見にくくなりそうな箇所に関しては、GitHubのURLを用意しておりますので、適宜ご活用くださいね。)
■ 本記事での試み
前回のその1では、「管理画面は管理者のみアクセス可能で、一般ユーザーがアクセスを試みるとトップページヘリダイレクトするようにする」を目的に実装を進めてきました。
そのため他の細部の部分、特に Post 機能においては、ログインできてしまえば誰でも他者の Post を編集、更新、削除ができてしまう状態にあります。本記事ではまずそうした Post 機能の不備を手直しし、投稿者自身もしくは管理者のみが Post を編集、更新、削除できるようにします。
その作業が完了した後、管理者がパートナーにアクセス権を付与する機能の実装と、パートナーのアクセス可能な範囲の設定(今回は Post の編集・更新・削除権限の付与)を行っていこうと思います。
箇条書きにすると以下の流れになります。
- Post 機能の手直し
- 管理者からアクセス権を付与する機能の実装
- Partner 機能に関するビューファイルの整備
- Partner が許された範囲での活動ができるまでの諸整備
- サーバーの起動と実装した部分の確認
- 本記事の最後に
[DEMO]
下の画像では、左側が管理者として管理画面にアクセスした場合、右側はパートナーとして管理者画面にアクセスした場合になります。管理者にはパートナーの新規登録から削除、ユーザーの削除機能を実装します。パートナーは新規のパートナー登録から削除、ユーザーの削除はできませんが、全ての Post の編集・更新・削除することが可能です。(パートナーに可能な機能は管理者も可能です。)
■ 開発環境・本記事終了時のコード(GitHub)
- OS:macOS Big Sur 11.2.3
- Ruby:3.0.0
- Ruby on Rails:6.1.3
- ローカル環境DB:Mysql
- テキストエディタ:Visual Studio Code
■ Post 機能の手直し
それでは、前回実装した Post 機能の手直しから始めましょう。
まずはトップページ(posts#index)の'Edit'、'Destroy'のリンクを、投稿者自身の場合のみ表示させるように直します。
app/views/posts/index.html.erb<% @posts.each do |post| %> <tr> <td><%= post.text %></td> <td><%= post.user.email %></td> <td><%= link_to 'Show', post %></td> <% if current_user.id == post.user_id %> <%# 追加 %> <td><%= link_to 'Edit', edit_post_path(post) %></td> <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td> <% end %> <%# 追加 %> </tr> <% end %>'Edit'、'Destroy'のリンク部分を「 if current_user.id == post.user_id 」「 end 」で囲うことで、ログインしているユーザーのIDと Post に登録されている user_id が一致しているかの分岐を行っています。(一致していれば(trueならば)、'Edit'、'Destroy'を表示させ、そうでなければ非表示にします。)
次に管理画面の投稿一覧の部分を修正して、管理者が Post の'Edit'と'Destroy'にアクセスできるようにします。具体的にはを以下のように td 行を追加します。
app/views/users/index.html.erb<table>==== 投稿一覧 ==== <thead> <tr> <th>投稿ID</th> <th>投稿内容</th> <th>投稿者ID</th> <th>投稿者メールアドレス</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @posts.each do |post| %> <tr> <td><%= post.id %></td> <td><%= post.text %></td> <td><%= post.user_id %></td> <td><%= post.user.email %></td> <td><%= link_to 'Edit', edit_post_path(post) %> <%# 追加 %> <td><%= link_to 'Destroy', post_path(post), method: :delete, data: { confirm: 'この投稿を本当に削除しますか?' } %></td> </tr> <% end %> </tbody> </table>続いてコントローラーも修正しましょう。
app/controllers/posts_controller.rbclass PostsController < ApplicationController before_action :set_post, only: %i[ show edit update destroy ] before_action :access_post, only: %i[ edit update destroy ] # before_action :access_post ※showは誰でも閲覧可能のため除外 # 省略 # def update # 管理者も更新できるようにaccess_post_paramsに変更 if @post.update(access_post_params) if current_user.email == Rails.application.credentials[:access_user] # updateに成功:管理者であった場合、users#index に遷移 flash[:message] = "変更が反映されました" redirect_to users_path else # updateに成功:管理者でない場合、posts#show に遷移 respond_to do |format| # 省略 # end end else # updateに失敗:管理者でも投稿者でも posts#show に遷移 respond_to do |format| # 省略 # end end end def destroy @post.destroy if current_user.email == Rails.application.credentials[:access_user] # destroy実行後:管理者であった場合、users#index に遷移 flash[:message] = "変更が反映されました" redirect_to users_path else # destroy実行後:管理者でない場合、posts#index に遷移 respond_to do |format| # 省略 # end end end private # 省略 # def post_params params.require(:post).permit(:text).merge(user_id: current_user.id) end # posts#edit,#update,#destroy の際に # 投稿者自身もしくは管理者でない場合は posts#index に遷移 def access_post unless current_user.id == @post.user_id || current_user.email == Rails.application.credentials[:access_user] flash[:message] = "アクセスをブロックしました" redirect_to root_path end end # posts#update の際に使用 def access_post_params params.require(:post).permit(:text).merge(user_id: @post.user_id) end end新たに before_action、access_post メソッド、access_post_params メソッド、Rails.application.credentials[:access_user] を利用した分岐などを加えております。
簡易的な説明になりますが、「 before_action :access_post 」で①ログインしているユーザーIDと Post に登録されているuser_idが一致しなかった場合、②ログインしているユーザーが管理者ではなかった場合、3つのアクション(#edit, #update, #destroy)においてはトップページ(posts#index)にリダイレクトさせるようにしています。
「 access_post 」メソッドは、update を実行する際、Post の user_id が投稿者のIDから管理者のIDへと上書きされてしまうのを防ぐようにしています。post_params では投稿者自身が更新を試みるときには問題がないのですが、管理者が更新を試みた際に、Post の user_id の部分が投稿者IDから管理者IDに書き換えられてしまいます。そのため、投稿された Post の user_id はそのままに中身(:text)のみ変更できるように「 params.require(:post).permit(:text).merge(user_id: @post.user_id) 」という形にしております。
先程の before_action :access_post のおかげで、#edit, #update, #destroy アクションを試みる前段階で、投稿者自身か管理者以外はトップページ(posts#index)に遷移させるのを実装できていますが、#update, #destroy アクションが成功した際に管理者は管理画面に、投稿者自身がアクションに成功した場合はトップページ(posts#index)に遷移するようにしたいですよね。
それを実現するために、#update, #destroyのアクション内に「 if current_user.email == Rails.application.credentials[:access_user] 」を使って、それぞれのアクションが成功した後に、ログイン中のユーザーが管理者であるかによって、遷移先を分岐させています。
以上で前回実装した部分の手直しは完了です。お疲れさまでした。
次の項目から管理者がアクセス権を付与する部分に触れていきますので、引き続き頑張りましょう!
■ 管理者からアクセス権を付与する機能の実装(モデル・コントローラーまで)
それでは管理者から他のユーザーに管理画面へのアクセス権を付与する機能の実装に取り掛かっていきましょう!大まかな流れとしては以下のようになります。
- Partner モデルの作成
- マイグレーションファイルの編集
- モデルの関係性の記載
- ルーティングの追記と User コントローラーの修正
- Partner コントローラーの作成
● Patner モデルの作成
まずはターミナルで以下のコマンドを入力して Partner モデルを作成します。
ターミナル$ rails g model Partner● マイグレーションファイルの編集
先程のコマンドで作成されたマイグレーションファイル(20..._create_partners.rb)を以下のように編集しましょう。
今回は付与するユーザーIDを、一意性制約及び外部キー制約を設けた上でDBに保存させます。(Partner モデルにおいても一意性制約を後ほど設けます。)
grant には付与したユーザーのメールアドレスが保存されるようにしますが、Partner モデルにおいて管理者用に設定したメールアドレスでログインしているユーザーによる付与なのかを検証させます。
db/migrate/20..._create_partners.rbclass CreatePartners < ActiveRecord::Migration[6.1] def change create_table :partners do |t| t.references :user, null: false, index: { unique: true }, foreign_key: true t.text :grant, null: false t.timestamps end end end編集が済んだらターミナルで rails db:migrate を実行します。
ターミナル$ rails db:migrate● モデルの関係性の記載
それでは次に、 User モデル と Partner モデルの関係性をそれぞれに記載しましょう。Partner は User に付与される関係性にあるため、Partner 側は belongs_to :user、User 側は has_one :partner にしました。
app/models/user.rbclass User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :posts, dependent: :destroy has_one :partner, dependent: :destroy # 追加 endapp/models/partner.rbclass Partner < ApplicationRecord belongs_to :user validates :user_id, uniqueness: true validates :grant, inclusion: { in: [Rails.application.credentials[:access_user]] } endvalidates :user_id, uniquenss: true でモデル側にも一意性制約を設けて、モデルとDB両方で一意性制約を設けている形になります。なぜモデルとDBの両方に一意性制約を設ける必要があるのかについては、「Ruby on Rails チュートリアル 第6章 ユーザーのモデルを作成する - 6.2.5 一意性を検証する -」に詳しく記載されているので、そちらを参照してください。
validates :grant, .... ですが、inclusion のバリデーションを使って、Rails.application.credentials[:access_user]で設定した管理者用のメールアドレスが grant で送られているかを検証しています。inclusion のバリデーションについては Rails ガイドを参照してください。
● ルーティングの追記と User コントローラーの修正
続いて、Partner を登録から削除までを行えるようにルーティングを設定していきましょう。今回は管理画面に Partner の一覧を表示させたいと思うので、resources :partners は、#new, #edit, #create, #update, #destroy のアクションに絞ります。
config/routes.rbRails.application.routes.draw do root to: "posts#index" devise_for :users resources :posts resources :users, only: [:index, :destroy] resources :partners, only: [:new, :edit, :create, :update, :destroy] # 追加 endそして、User コントローラーの index で Partner の一覧を表示させるために、以下の1文を追加します。
app/controllers/users_controller.rbclass UsersController < ApplicationController before_action :access_user layout "access_layout" def index @users = User.all @posts = Post.includes(:user) @partners = Partner.includes(:user) # 追加 end ### 以下略 #### end● Partner コントローラーの作成
では次に、Partner コントローラーの作成とその中身を記述していきましょう!
まずはターミナルで以下のコマンドを入力して Partner コントローラーと、それに付随するファイルを作成します。ターミナル$ rails g controller partners先程のコマンドで作成された partners_controller.rb を、以下のように記載します。
app/controllers/partners_controller.rbclass PartnersController < ApplicationController layout "access_layout" before_action :set_partner, only: %i[ edit update destroy ] before_action :access_partner, only: %i[ new edit create update destroy] def new @partner = Partner.new end def edit end def create @partner = Partner.new(partner_params) if @partner.save flash[:message] = "パートナーを登録しました" redirect_to users_path else render :new end end def update if @partner.update(partner_params) flash[:message] = "変更が反映されました" redirect_to users_path else flash[:message] = "変更が反映されませんでした" redirect_to edit_partner_path end end def destroy @partner.destroy flash[:message] = "パートナー関係を解消しました" redirect_to users_path end private def set_partner @partner = Partner.find(params[:id]) end def partner_params params.require(:partner).permit(:user_id).merge(grant: current_user.email) end # 管理者でない場合はトップページ(posts#index)に遷移 def access_partner unless current_user.email == Rails.application.credentials[:access_user] flash[:message] = "アクセスをブロックしました" redirect_to root_path end end endここでまず注目して欲しいのは、partner_params のコードです。merge(grant: current_user.email) と記載することにより、ログインしているユーザーのメールアドレスをgrant カラムに保存するようにしています。先程の Partner モデルの記載を思い出して欲しいのですが、
app/models/partner.rb### 省略 ### validates :user_id, uniqueness: true validates :grant, inclusion: { in: [Rails.application.credentials[:access_user]] } ### 省略 ###上記の記述により、以下のケースにおいて、バリデーション機能が働いてDBへの保存を阻止します。
- user_id カラムに既に同じ値が登録されていた場合
- grant (current_user.email)が管理者用メールアドレスと一致しない場合
次に、access_partner メソッドで、ログインしているユーザーのメールアドレスと管理者用に設定したメールアドレスが一致しない場合、トップページ(posts#index)にリダイレクトさせています。また、access_partner メソッドを before_action に設定し、全てのアクションに適応することで、Partner に関しては管理者のみアクセスできる制約を設けています。
■ Partner 機能に関連するビューファイルの整備
続いて、Partner 機能に関連するビューファイルを整えましょう。app/views/partners フォルダに、手動で以下の3ファイルを作成及び記載します。
app/views/partners/new.html.erb<h1>New Partner</h1> <%= render 'form', partner: @partner %> <%= link_to 'Back', users_path %>app/views/partners/edit.html.erb<h1>Editing Partner</h1> <%= render 'form', partner: @partner %> <%= link_to 'Back', users_path %>app/views/partners/_form.html.erb<%= form_with(model: partner) do |form| %> <% if partner.errors.any? %> <div id="error_explanation"> <h2> <%= pluralize(partner.errors.count, "error") %> prohibited this partner from being saved: </h2> <ul> <% partner.errors.each do |error| %> <li><%= error.full_message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.label :user_id %> <%= form.number_field :user_id %> </div> <div class="actions"> <%= form.submit %> </div> <% end %>_form.html.erb の <%= form.number_field :user_id %> という箇所で、管理者がアクセス権を付与するユーザーIDを入力するフォームになっています。
次にパートナー一覧を管理画面(users#index)で表示できるように、app/views/users/index.html.erb 内に以下を加筆します。
app/views/users/index.html.erb<h1>管理画面</h1> <%# ↓追加↓ %> <% if current_user.email == Rails.application.credentials[:access_user] %> <p> <%= link_to 'New_Partner', new_partner_path %> </p> <% end %> <table>==== パートナー一覧 ==== <thead> <tr> <th>パートナーID</th> <th>ユーザーID</th> <th>メールアドレス</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @partners.each do |partner| %> <tr> <td><%= partner.id %></td> <td><%= partner.user_id %></td> <td><%= partner.user.email %></td> <% if current_user.email == Rails.application.credentials[:access_user] %> <td><%= link_to 'Edit', edit_partner_path(partner) %></td> <td><%= link_to 'Destroy', partner_path(partner), method: :delete, data: { confirm: 'パートナー関係を解消しますか?' } %></td> <% end %> </tr> <% end %> </tbody> </table> <br> <%# ↑追加↑ %> <%# 以下略 %>これで Partner の一覧表示から削除(index ~ destroy)まで整いましたが、まだ不十分です。現状だとアクセス権を付与されたユーザーが管理画面にアクセスすることもできなければ、Post 内容を編集・更新・削除することもできません。次の項目でそれらを整備していきましょう!
■ Partner が許された範囲での活動ができるまでの諸整備
まずは 以下の2つを実装するために User コントローラーを編集しましょう。
- 管理画面(users#index)にパートナーがアクセスできるようにする。
- User の削除は管理者のみ可能なように制約を設ける。
app/controllers/users_controller.rbclass UsersController < ApplicationController before_action :access_user, only: %i[ index ] before_action :action_permit, only: %i[ destroy ] layout "access_layout" # 省略 # private def access_user unless current_user.email == Rails.application.credentials[:access_user] || !current_user.partner.nil? flash[:message] = "アクセスをブロックしました" redirect_to root_path end end def action_permit unless current_user.email == Rails.application.credentials[:access_user] flash[:message] = "権限が与えられていません" redirect_to users_path end end end(上記の全容コード:https://github.com/tsuchiya-yu2/access_test2/blob/master/app/controllers/users_controller.rb )
次に、パートナーに全ての Post に対して編集・更新・削除ができるように、Post コントローラを編集して権限を付与しましょう。
app/controllers/posts_controller.rbclass PostsController < ApplicationController before_action :set_post, only: %i[ show edit update destroy ] before_action :access_post, only: %i[ edit update destroy ] # 省略 # def update if @post.update(access_post_params) if current_user.email == Rails.application.credentials[:access_user] || !current_user.partner.nil? # 省略 # else # 省略 # end else # 省略 # end end def destroy @post.destroy if current_user.email == Rails.application.credentials[:access_user] || !current_user.partner.nil? # 省略 # else # 省略 # end end private # 省略 # def access_post if current_user.id == @post.user_id elsif current_user.email == Rails.application.credentials[:access_user] || !current_user.partner.nil? else flash[:message] = "アクセスをブロックしました" redirect_to root_path end end # 省略 # end(上記の全容コード:https://github.com/tsuchiya-yu2/access_test2/blob/master/app/controllers/posts_controller.rb )
続いて、パートナーがログインした際の header に、'管理画面'のリンクが表示されるように app/views/lyouts にある application.html.erb と access_layout.html.erb を編集します。
app/views/layouts/application.html.erb<% if user_signed_in? %> <%= link_to 'ログアウト', 省略 %> <% if current_user.email == Rails.application.credentials[:access_user] || !current_user.partner.nil? %> ||| <%= link_to '管理画面', users_path %> <% end %> <% else %> <%# 省略 %> <% end %>(上記の全容コード:https://github.com/tsuchiya-yu2/access_test2/blob/master/app/views/layouts/application.html.erb )
(下記の全容コード:https://github.com/tsuchiya-yu2/access_test2/blob/master/app/views/layouts/access_layout.html.erb )app/views/layouts/access_layout.html.erb<% if user_signed_in? %> <%= link_to 'ログアウト', 省略 %> <% if current_user.email == Rails.application.credentials[:access_user] %> ||| <%= link_to '管理画面', users_path %> <% end %> <% else %> <%# 省略 %> <% end %>最後に、ユーザーを 'Destroy' できるリンクが、管理者のみに表示されるように制約を設けます。
app/views/users/index.html.erb<h1>管理画面</h1> <%# 省略 %> <table>==== ユーザー一覧 ==== <thead> <tr> <th>ユーザーID</th> <th>メールアドレス</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @users.each do |user| %> <tr> <td><%= user.id %></td> <td><%= user.email %></td> <% ##### ↓追加↓ ##### %> <% if current_user.email == Rails.application.credentials[:access_user] %> <td><%= link_to 'Destroy', user_path(user), method: :delete, data: { confirm: 'ユーザーを本当に削除しますか?' } %></td> <% end %> <% ##### ↑追加↑ ##### %> </tr> <% end %> </tbody> </table> <br> <%# 省略 %> <%= link_to '一般トップページへ', root_path %>(上記の全容コード:https://github.com/tsuchiya-yu2/access_test2/blob/master/app/views/users/index.html.erb )
■ サーバーの起動と実装した部分の確認
作業お疲れさまでした。
これで管理者がパートナーにアクセス権を付与する機能の実装と、パートナーのアクセス権の設定(今回は Post の編集・更新・削除権限の付与)を実装できました。実際に rails s コマンドを実行してサーバーを立ち上げて確認してみてください。ターミナル$ rails s
- 管理者に設定したメールアドレスで管理画面へアクセスした場合と、パートナー登録を受けたユーザーで管理画面へアクセスした場合で、管理画面の違いは確認できたでしょうか?
- パートナー状態の管理画面において、Post の変更・更新・削除ができましたか?
[DEMO]
下の画像は、左が管理者として管理画面にアクセスした場合、右がパートナーとして管理画面にアクセスした場合になります。
■ 本記事の最後に
本記事は以上になります。お疲れさまでした。
credentials.yml を使っての管理画面の実装は終了になります。UIの改良や Post に楽観的ロックを導入したりと、いろいろと手を付けたい所はありますが、当初の目的は果たせたと思います。
個人的な振り返りになりますが、本実装の良い点はcredentials を利用しているので、管理者が誰であるのかがコード上(GitHub含む)では分からないところだと思います。
また、devise のメール認証などを実装し、パートナー登録を終えた後に、管理者IDを削除して管理者ID不在にしておくことで、セキュリティを向上させられる余地があるところも良い点と考えます。
(仮に他者が管理者用のメールアドレスを特定し、そのメールアドレスでアカウントを作成しようとしても、アプリケーションから送信される認証メールを開くためには、別途手間やセキュリティを潜らなければならなくなります。仮にgmailであれば、gmailを開くパスワードを入手し得ない限りは、本アプリケーションに管理者として成り代わってアクセスすることはできません。)
本記事で作成したアプリケーションのコードは、上記のGitHub上からも閲覧できますので適宜ご活用ください。
最後に
ここまで読んでいただき、ありがとうございました!!
- 投稿日:2021-03-25T23:08:04+09:00
?preloadとeager_loadの使い分けについて
preloadとeager_loadをどのようにして使い分けるかのメモです。
※議論の余地がかなりあるという前提です
前提条件:全てのレコードを取得するような場合
- 条件を指定する(whereなどを使う)ような場合は、eager_loadを使う。(テーブル結合していなければ、そもそも関連先の情報がわからないためpreloadは使えない)
- 条件を指定しない場合は、preload、each_loadの使い分けはケースバイケース。所得したいデータのカラムが少ないならeach_loadを使って一つのクエリで済ませるべきだし、多いならpreload使った方がいいかも。基本的には、レスポンスタイムはpreload使った方が早い。
前提条件:全てのレコードを取得する+関連先のデータが1対1であるような場合
- 1対1であるかつ条件を指定しない場合、eager_loadを使うことで結合してからまとめて取得する方が効率が良い場合が多い。 (1対1になるようなデータを持ってくる場合は、抽象的ですが関連度がかなり強いので結合していった方が効率が多い場合が多いという解釈。company_userとcompany_user_profile的な!)
- 1対1であるかつ条件を指定する(whereなどを使う)ような場合は当然eager_loadが当てはまる。
前提条件:全てのレコードを取得する+関連先のデータが1対多であるような場合
- 1対多であるかつ条件を指定しない場合、includesの挙動通りpreloadを使う
- 1対多であるかつ条件を指定する(whereなどを使う)ような場合、結合しなければいけないのでeager_loadを使うしかない
注意点
- ここまでの考えであっているのなら、一対一のときはeager_loadを使う場合が良いのかもしれないが結合してもデータが重複するような場合がある。その時は、preloadを使うのも検討。なぜなら、eager_loadにはdistinctが備わっていないために指定したデータ数以上のデータを取ってきてしまう可能性があるため。
- preloadを使う時に、最初のクエリのデータ取得量が多すぎるとin句内の膨大なデータに対してSQL自体の設定値やメモリサイズの設定値を考慮しなければいけない
- includesはeager_loadとpreloadを判断するのに時間がかかる、また状況を考えたクエリでのデータ取得操作が悪いのであまり使うべきでない。
参考記事
- ActiveRecordのincludes, preload, eager_load の個人的な使い分け
- Rails: JOINすべきかどうか、それが問題だ — #includesの振舞いを理解する(翻訳)
- なぜ、SQLは重たくなるのか?──『SQLパフォーマンス詳解』の翻訳者が教える原因と対策
- 投稿日:2021-03-25T23:04:31+09:00
Rooで取り込んだExcelの日時のデータがうまく反映されない
こんにちは
エラーが出た背景
rooを使ってexcelの日時のデータを取り込むよう開発を進めました。
ある程度できあがって確認しようとすると、下記のようなエラーが出ました。
おそらく,in_time_zone
メソッドがinteger型に対応できていないと
下記に
- エラーメッセージが出た部分
- 対応するメソッド(controller)
- エラーが発生したファイル
を載せています。app/controller/ir/meeting_logs_controller.rbdef time_from_excel_date_time(excel_date, excel_time) date = excel_date.in_time_zone if excel_time.is_a?(String) time = excel_time.to_time hour = time.hour minute = time.min elsif excel_time.is_a?(Integer) hour = (excel_time / 3600) minute = (excel_time % 3600 / 60) end date + hour.hour + minute.minute end普段取り込むexcelファイル(該当箇所のみ)
id 日付 開始時間 12/9 1:00 12/8 1:00 11/27 1:00 11/26 1:00 今回エラーが発生したexcelファイル(該当箇所のみ)
id 日付 開始時間 12月9日 1:00 12月8日 1:00 11月27日 1:00 11月26日 1:00 原因
上の部分を見ていただければわかる通り、
日付
の区切られている部分が/
か月日
かの違いによるものでした。
この部分が違うと、
/
だとそのまま(String型)、
月日
だと数字(Integer型)
が変数として取り込まれるので、String型にしか対応していなかったメソッドでエラーが発生してしまいました。改善策
そのためcontrollerを書き換えました。
app/controller/ir/meeting_logs_controller.rbdef time_from_excel_date_time(excel_date, excel_time) EXCEL_EPOCH = 2209078800 TICKS_PER_DAY = 60 * 60 * 24 if excel_date.is_a?(String) || excel_date.is_a?(Date) date = excel_date.in_time_zone elsif excel_date.is_a?(Integer) # 日付が漢字の場合、integer型で受け取る => 1899/12/31 からどれくらいの日数がたったかを表している # Unixのゼロタイム(基準)が "1970/1/1" に設定されている為、下記ステップで日付を求める # 1. TICKS_PER_DAY をかけて、1899/12/31 からどれくらいの秒数がたったかを計算 # 2. 1から EXCEL_EPOCH 秒をを引き、1970/1/1 からどれくらいの秒数がたったかを計算 unix_timestamp = excel_date * TICKS_PER_DAY - EXCEL_EPOCH date = Time.at(unix_timestamp).to_datetime - 8.hours - 1.day end if excel_time.is_a?(String) time = excel_time.to_time hour = time.hour minute = time.min elsif excel_time.is_a?(Integer) hour = (excel_time / 3600) minute = (excel_time % 3600 / 60) end date + hour.hour + minute.minute endexcelから取り込んだ日付の変数が入っている
excel_date
に対して、if文でString型とInteger型に分けて処理を走らせることにしました。
また、unix_timestamp
の部分が複雑なので下記に説明をしたいと思います。unixとexcel
このコントローラーの記述は主にunixとexcelの基準の時間を合わせるために書きました。
コメントアウトでも書いてありますが、
excelは基準が1899/12/31
なので帰ってくる変数は、1899/12/31から何日たっているか
を表します。
しかし、Rubyに限らずunixを基準としているプログラミング言語は1970/1/1(ゼロタイム)
を基準に作動します。
なので、excelの変数をunixの基準に合わせるためにunix_timestamp = excel_date * TICKS_PER_DAY - EXCEL_EPOCHの記述をしています。
最後に
今回僕の初めての投稿なので至らない点があると思いますが、
僕なりに一生懸命頑張ったつもりです。笑
もし、何かアドバイスなどありましたらぜひ教えていただきたいです!
- 投稿日:2021-03-25T22:55:53+09:00
Rails gem bcryptのメソッドが使えない
はじめに
初めまして。私はプログラミングを勉強してまだ間もない駆け出しのエンジニアです。Qiitaへの投稿も含めまだまだ勉強中です。そしてこれがQiitaへの初投稿となりますのでお手柔らかにお願いします。
主に初心者の方向け、また自分用のメモとしてこれから発信していきます。開発環境
Rails 6.1.3 ローカル環境でProgateのTweet_Appを作成中
概要
今回はタイトルにもある通り、Gemfileへbcryptを追加したにも関わらず、has_secure_passwordやauthenticateといったメソッドが使えない!と言う状況に出くわしたのでそちらを共有していきます。
まず、
Gemfileにgem 'bcrypt'
を追加。
その後ターミナルでbundle install
を実行。パスワードのハッシュ化を実装させていこうと
has_secure_passwordメソッド
を記述models/user.rbclass User < ApplicationRecord has_secure_password確認のため作成中のサイトを見たところ、そのメソッドは知らないよとのエラーが。
使えるはずのメソッドが使えずかなり焦った。原因は、bcryptのバージョン?・・・いやバージョンは指定せず記述したので最新のものが導入されているはず。
じゃあ一体なんでだろうと小一時間悩んだ挙句ようやく原因を突き止めた。rails s の再起動
サーバーを立ち上げ直すことでエラーは解消された。
長いこと悩んだ問題の原因はなんとも簡単なことだった。
以前、テーブルのcreated_atカラムを日本時間にしたいなと思い立ち、Qiitaなどを参考にしたときにGemfileの編集をしたことがあった。その時参考にした記事に「サーバーを再起動させて変更完了です。」の一文があったことを思い出した。まとめ
自分と同じようなことで悩んでいた方がもしいたら、無駄な時間を過ごすことがなくなればいいなと思います。
rails s の再起動はProgateでGemfileのレッスンで書かれてなかったぞ・・・
それとも正規の解決法が他にあるのか?まあ解決できればそれでいいか!またネタがあったら投稿したいと思います。
以上
- 投稿日:2021-03-25T22:55:53+09:00
Rails Gemfileでbcrypt追加後にメソッドが使えない
はじめに
初めまして。私はプログラミングを勉強してまだ間もない駆け出しのエンジニアです。Qiitaへの投稿も含めまだまだ勉強中です。そしてこれがQiitaへの初投稿となりますのでお手柔らかにお願いします。
主に初心者の方向け、また自分用のメモとしてこれから発信していきます。開発環境
Rails 6.1.3 ローカル環境でProgateのTweet_Appを作成中
概要
今回はタイトルにもある通り、Gemfileへbcryptを追加したにも関わらず、has_secure_passwordやauthenticateといったメソッドが使えない!と言う状況に出くわしたのでそちらを共有していきます。
Gemfileに
gem 'bcrypt'
を追加。
その後ターミナルでbundle install
を実行。さあ、学んだパスワードのハッシュ化を実装させていこうと
has_secure_passwordメソッド
を記述models/user.rbclass User < ApplicationRecord has_secure_password確認のため作成中のサイトを見たところ、そのメソッドは知らないよとのエラーが。
使えるはずのメソッドが使えずかなり焦った。原因は、bcryptのバージョン?・・・いやバージョンは指定せず記述したので最新のものが導入されているはず。
じゃあ一体なんでだろうと小一時間悩んだ挙句ようやく原因を突き止めた。rails s の再起動
長いこと悩んだ問題の原因はなんとも簡単なことだった。
以前、テーブルのcreated_atカラムを日本時間にしたいなと思い立ち、Qiitaなどを参考にしたときにGemfileの編集をしたことがあった。その時参考にした記事に「サーバーを再起動させて変更完了です。」の一文があったことを思い出した。まとめ
自分と同じようなことで悩んでいた方がもしいたら、無駄な時間を過ごすことがなくなればいいなと思います。
rails s の再起動はProgateでGemfileのレッスンで書かれてなかったぞ・・・
それとも正規の解決法が他にあるのか?まあ解決できればそれでいいか!またネタがあったら投稿したいと思います。
以上
- 投稿日:2021-03-25T21:47:48+09:00
mimemagicエラー
gemを入れてbundle install を行ったところ、以下のエラーが出ました。
Your bundle is locked to mimemagic (0.3.5), but that version could not be found
in any of the sources listed in your Gemfile. If you haven't changed sources,
that means the author of mimemagic (0.3.5) has removed it. You'll need to update
your bundle to a version other than mimemagic (0.3.5) that hasn't been removed
in order to install.んん、よく分からん。。とりあえずGemfile.lockで関係してそうな内容を消して再度bundle install をしたら直りました。
- 投稿日:2021-03-25T21:47:44+09:00
Twitter API 登録の仕方(2021年3月17日)
【欲しいもの】
bot を作るために必要なもの。
1. Access Token
2. Access Token Secret
3. Consumer Key
4. Consumer Secret
これらを以下で取得していく。準備編
1
ここにアクセスする
2
Apply(右上)
3
Apply for a developer account
4
目的を選ぶ(今回はbotを作りたいのでhobbyist > making a bot)
5
get start
6
名前とかemailとか入力する
7
何に使うのか入力する
利用規約に同意する
色々進めて、、、8
submit application
メールが送られたっぽい9
メールにある[Confirm your email]をクリック
メールアドレス、パスワードを打って認証完了する。10
「今あなたのレビューをしているよ!!」的なメールが届く。
他の人の記事を見ているとレビュー完了まで数時間かかるそう。###11 メールがかえってくる。
今レビューしていますが、もう少し用途について聞かせてください的な内容。
これは、7.で英文と全く同じのでもOK12
30程度待っていると、twitterからメールが来る
登録申請がapproveされたメールがきました。13
送られてきたリンクにアクセスして、アプリ名を決める。
Get keyを押す。14
【api key】
【API secret key】
【Bearer token】
を保存しておく。15
作ったアプリの中からAccess token & secretをgenerateする。
そこに、Access token、Access token secretがあるからコピーしてどこかに記録しておく。16
これで最初に述べたAccess Token、Access Token Secret、Consumer Key、Consumer Secretの4つがゲットできた。
ここからは本格的にTwitter bot を作っていく。
https://qiita.com/ryoya-s/items/bc8a0e39716bb2844f0b
の記事を参考にした。
- 投稿日:2021-03-25T21:39:25+09:00
User.allって良くないの?って話
こんにちは。たにーです。
今回は、チーム開発で少し議論した
「アクション内でのでのallは良くない?」についてです。
items_controller.rb@items_all = Item.all結論
結論から言うと、悪いことはないが
場面によっては使い方を考えなくてはいけないということです。カリキュラムで作成したアプリでは、
レコード数がmax10個ぐらいで試していたこともあり、取り出すデータ量が少ないため問題なかった。もし、その数が100個、1000個、1万個あった場合だと、
情報量が多すぎて、処理速度が遅くなり、ページのロードが遅いなどが起きるかもしれません。なので、その処理速度をより早くする書き方をご紹介します。
状況について
- railsでwebアプリケーションを開発中。
- 販売している商品数をviewに表示させたい。
例:( 商品一覧(全:〇〇件) )- viewとcontrollerには下記のように書いていた。
index.html.erb<div class="container"> <div class="row"> <div class="col-sm-12 px-sm-0"> <h2>商品一覧(全<%= @items_all.count %>件)</h2> </div> </div>items_controller.erbclass Public::ItemsController < ApplicationController def index @items_all = Item.all end実際にターミナルを見て確認します。
まずは、そのままでページを開いてみます。
そうすると、、、、、(item.allの場合)Started GET "/" for 106.180.147.162 at 2021-03-25 11:43:45 +0000 Cannot render console from 106.180.147.162! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by Public::HomesController#top as HTML Rendering public/items/index.html.erb within layouts/application (0.2ms) SELECT COUNT(*) FROM "items" ↳ app/views/public/items/index.html.erb:4 Item Load (0.1ms) SELECT "items".* FROM "items" LIMIT ? OFFSET ? [["LIMIT", 8], ["OFFSET", 0]] ↳ app/views/public/items/index.html.erb:8見て欲しいところはここです。
(item.allの場合)Item Load (0.3ms) SELECT "items".* FROM "items" ORDER BY "items"."created_at" DESC LIMIT ? [["LIMIT", 4]]
Item Loadの(0.3ms)、と書いてあります。
この数値が低ければ低いほど応答速度が速い(タイムラグが少ない)と言われています。
もしかしたら、不要なデータを取得してきているから
0.3なのか?書き方でより少なくできるのでは?と気になったところでチームメンバーで解決策を探しました。実際に調べて試しました
selectで試した
items_controller.erbdef index @items_all = Item.select(:id) end(Item.selectの場合)Started GET "/items" for 106.180.147.162 at 2021-03-25 12:13:24 +0000 Cannot render console from 106.180.147.162! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by Public::ItemsController#index as HTML Rendering public/items/index.html.erb within layouts/application (0.1ms) SELECT COUNT("items"."id") FROM "items" ↳ app/views/public/items/index.html.erb:4 Item Load (0.1ms) SELECT "items".* FROM "items" LIMIT ? OFFSET ? [["LIMIT", 8], ["OFFSET", 0]] ↳ app/views/public/items/index.html.erb:82箇所あるますが、それでも0.2msで早くなっているのがわかります。
countで試した
items_controller.erbclass Public::ItemsController < ApplicationController def index @items_all = Item.count end(Item.count)Started GET "/items" for 106.180.147.162 at 2021-03-25 12:22:09 +0000 Cannot render console from 106.180.147.162! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by Public::ItemsController#index as HTML (0.1ms) SELECT COUNT(*) FROM "items" ↳ app/controllers/public/items_controller.rb:4 Rendering public/items/index.html.erb within layouts/application Item Load (0.2ms) SELECT "items".* FROM "items" LIMIT ? OFFSET ? [["LIMIT", 8], ["OFFSET", 0]]こちらは,0.3msであまり変わっていない、、、
結果としては、
メソッド 応答速度 all 0.3ms select 0.2ms count 0.3ms selectで特定のカラムを指定する「select」で件数を取得する方法が今の段階では良さそうです!!
もし、違った方法、間違っているなどあれば教えていただけますと幸いです。以上、たにーでした。
参考文献
- 投稿日:2021-03-25T21:39:25+09:00
allメソッドって良くないの?って話
こんにちは。たにーです。
今回は、チーム開発で少し議論した
「アクション内でのでのallは良くない?」についてです。
items_controller.rb@items_all = Item.all結論
結論から言うと、悪いことはないが
場面によっては使い方を考えなくてはいけないということです。カリキュラムで作成したアプリでは、
レコード数がmax10個ぐらいで試していたこともあり、取り出すデータ量が少ないため問題なかった。もし、その数が100個、1000個、1万個あった場合だと、
情報量が多すぎて、処理速度が遅くなり、ページのロードが遅いなどが起きるかもしれません。なので、その処理速度をより早くする書き方をご紹介します。
状況について
- railsでwebアプリケーションを開発中。
- 販売している商品数をviewに表示させたい。
例:( 商品一覧(全:〇〇件) )- viewとcontrollerには下記のように書いていた。
index.html.erb<div class="col-sm-12 px-sm-0"> <h2>商品一覧(全<%= @items_all.count %>件)</h2> </div>items_controller.erbclass Public::ItemsController < ApplicationController def index @items_all = Item.all end実際にターミナルを見て確認します。
まずは、そのままでページを開いてみます。
そうすると、、、、、(item.allの場合)Started GET "/" for 106.180.147.162 at 2021-03-25 11:43:45 +0000 Cannot render console from 106.180.147.162! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by Public::HomesController#top as HTML Rendering public/items/index.html.erb within layouts/application (0.2ms) SELECT COUNT(*) FROM "items" ↳ app/views/public/items/index.html.erb:4見て欲しいところはここです。
(item.allの場合)(0.2ms) SELECT COUNT(*) FROM "items" ↳ app/views/public/items/index.html.erb:4
(0.2ms)、と書いてあります。
この数値が低ければ低いほど応答速度が速い(タイムラグが少ない)と言われています。
もしかしたら、不要なデータを取得してきているから
0.2なのか?書き方でより少なくできるのでは?と気になったところでチームメンバーで解決策を探しました。実際に調べて試しました
selectで試した
items_controller.erbdef index @items_all = Item.select(:id) end(Item.selectの場合)Started GET "/items" for 106.180.147.162 at 2021-03-25 12:13:24 +0000 Cannot render console from 106.180.147.162! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by Public::ItemsController#index as HTML Rendering public/items/index.html.erb within layouts/application (0.1ms) SELECT COUNT("items"."id") FROM "items" ↳ app/views/public/items/index.html.erb:4それでも0.2msで早くなっているのがわかります。
countで試した
items_controller.erbclass Public::ItemsController < ApplicationController def index @items_all = Item.count end(Item.count)Started GET "/items" for 106.180.147.162 at 2021-03-25 12:22:09 +0000 Cannot render console from 106.180.147.162! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by Public::ItemsController#index as HTML (0.1ms) SELECT COUNT(*) FROM "items"こちらも、0.1msと早くなってるのかな?
結果としては、
メソッド 応答速度 all 0.2ms select 0.1ms count 0.1ms もし、違った方法、間違っているなどあれば教えていただけますと幸いです。
以上、たにーでした。
参考文献
- 投稿日:2021-03-25T21:32:17+09:00
【Rails6】flatpickrカレンダーの導入で気をつける事
自作ポートフォリオを作成している時に、bootstrapのカレンダーが使いづらかった為、flatpickrを導入する事にしました。その時に躓いたポイントがあったので、シェアします。
開発環境
- macOS Catalina 10.15.7
- Ruby 2.7.2
- Rails 6.1.1
すでに何かしらのアプリを作っている前提で進めていきます。
まずはこちらの記事をベースにflatpickrを導入
気をつけないといけなかった点
上記の記事で、
<!-- ***** 以下を追加 ***** --> <%= form_with model: @calendar do |form| %> <input id ="calendar_form" type="text" name="calendar[date]" readonly="readonly" > <%= form.submit "送信" %> <% end %> <!-- ***** 以上を追加 ***** -->という部分があるのですが、
僕のアプリはこのようなフォーム設計になっています。
view<%= f.label :visit_date %> <input id="calendar_form" type="text" name="visit_history[visit_date]" placeholder="日付を設定" class="form-control" readonly="readonly">ここで
name="コントローラー名[バリュー名]
という形にし、下記に記載しているコントローラーに合わせてあげる必要があります。visit_histories_controller.rbclass VisitHistoriesController < ApplicationController before_action :set_visit_history, only: [:show, :edit, :update, :destroy] # GET /visit_historys # GET /visit_historys.json def index @visit_histories = VisitHistory.all end # GET /visit_historys/1 # GET /visit_historys/1.json def show @visit_history end # GET /visit_historys/new def new @visit_history = VisitHistory.new(visit_history_params) @visit_history.build_medical_treatment_history end # GET /visit_historys/1/edit def edit end # POST /visit_historys # POST /visit_historys.json def create @visit_history = current_user.visit_histories.new(visit_history_params) if @visit_history.save redirect_to client_path(@visit_history.client_id), notice: "VisitHistory was successfully created." else render :new end end # PATCH/PUT /visit_historys/1 # PATCH/PUT /visit_historys/1.json def update if @visit_history.update(visit_history_params) redirect_to @visit_history, notice: "VisitHistory was successfully updated." else render :edit end end # DELETE /visit_historys/1 # DELETE /visit_historys/1.json def destroy @visit_history.destroy redirect_to client_path(@visit_history.client_id), notice: "VisitHistory was successfully destroyed." end private # Use callbacks to share common setup or constraints between actions. def set_visit_history @visit_history = VisitHistory.find(params[:id]) end # Only allow a list of trusted parameters through. def visit_history_params params.require(:visit_history).permit(:visit_date, :fee, :client_id, medical_treatment_history_attributes: [:user_id, :subjective, :objective, :assessment, :plan, :memo]) end endここで、さきほどの
name="コントローラー名[バリュー名]
が合っていないと、
ストロングパラメーターのpermitの部分で弾かれてしまい、@visit_hisrotyの中のvisit_date
の値がnil
になってしまいます。失敗例
あまり良く理解して出来ていなかったため、はじめは
name="calendar[date]
やname="calendar[visit_date]
で試していました。この場合、先程の通りストロングパラメーターで弾かれて、
visit_date
の値がnil
になります。binding.pryでパラメーターを確認してみました。
visit_date
の値がnil
になっています。ターミナル[1] pry(#<VisitHistoriesController>)> params => #<ActionController::Parameters {"authenticity_token"=>"ADamDRCkllatE4r75IMx5YaVQSkqML1tkzc6zhm9uFtqgsQ6uG0JbKWpe4PC8AAryLjP3587W5233WLlp_dqDQ", "visit_history"=>#<ActionController::Parameters {"client_id"=>"1", "fee"=>"5000", "medical_treatment_history_attributes"=>{"user_id"=>"1", "subjective"=>"", "objective"=>"", "assessment"=>"", "plan"=>"", "memo"=>""}} permitted: false>, "calendar"=>#<ActionController::Parameters {"visit_date"=>"2021-03-25"} permitted: false>, "commit"=>"登録", "controller"=>"visit_histories", "action"=>"create"} permitted: false> [2] pry(#<VisitHistoriesController>)> @visit_history => #<VisitHistory:0x00007fd57424f710 id: 20, visit_date: nil, fee: 5000, client_id: 1, user_id: 1, created_at: Thu, 25 Mar 2021 17:49:26.938352000 JST +09:00, updated_at: Thu, 25 Mar 2021 17:49:26.938352000 JST +09:00>成功例
visit_date
の中に値がしっかりと入っています。ターミナル[1] pry(#<VisitHistoriesController>)> params => #<ActionController::Parameters {"authenticity_token"=>"QXCgqasqGOeA9w-vtKOevhC8Bz9e-WHQ8yWr1nYd9skrxMKeA-OH3YhN_teS0K9wXpGJyevyhyDXz_P9yFcknw", "visit_history"=>#<ActionController::Parameters {"client_id"=>"1", "visit_date"=>"2021-03-28", "fee"=>"9000", "medical_treatment_history_attributes"=>{"user_id"=>"1", "subjective"=>"", "objective"=>"", "assessment"=>"", "plan"=>"", "memo"=>""}} permitted: false>, "commit"=>"登録", "controller"=>"visit_histories", "action"=>"create"} permitted: false> [2] pry(#<VisitHistoriesController>)> @visit_history => #<VisitHistory:0x00007fc42c874c48 id: 23, visit_date: Sun, 28 Mar 2021, fee: 9000, client_id: 1, user_id: 1, created_at: Thu, 25 Mar 2021 19:17:45.940796000 JST +09:00, updated_at: Thu, 25 Mar 2021 19:17:45.940796000 JST +09:00>まとめ
Rails6でflatpickrを導入する際の記事がほとんど英語のものしか無かったので、今回記事としてまとめてみました。見ていただいた方の参考になれば幸いです。
- 投稿日:2021-03-25T21:26:50+09:00
【Rails&heroku】MySQLで出来てた「あいまい検索」がPostgreSQLで出来ない場合にやること
AWSでコード完成、いざherokuへデプロイ!・・・したけどエラー。
調べてみると、あいまい検索の部分がおかしいらしい。【ページ内リンク】
0.環境
1.ソースコード
2.そもそもあいまい検索部分が原因だと分かった経緯
3.解決策0.環境
・AWS
・heroku/7.48.0 linux-x64 node-v12.16.2
・Rails 5.2.4.5
・ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
・MySQL 5.7.31
・PostgreSQL 9.2.241.ソースコード
Example.rb@teams = Team.where("#{key} like ?", "%#{value}%")・いたって普通のあいまい検索。
key
がキー、value
が値。
【例:key = "id"
、`value = "(検索用に入力した値)"】
・MySQLだと上手くいったのに、PostgreSQLだとエラーが生じた。※ちなみに、下記に2通り完全一致検索方法を書いたが、方法1はどちらでも作動し、方法2は
PostgreSQL
では作動しなかった。Example2.rb@teams = Team.where("#{key} = #{value}") #方法1 @teams = Team.where("#{key} like ?", "#{value}") #方法2たぶん「
like
」が悪そう。2.そもそもあいまい検索部分が原因だと分かった経緯
$ heroku logs -t
heroku logs --tail
の略。これを打てば、どこでエラーが出たか一発で分かる。3.解決策
調べてみると、
key
とvalue
の型が違うのが原因らしい。Example.rb@teams = Team.where("cast(#{key} as text) like ?", "%#{value}%")PostgreSQLなら、これで良い。
cast
、RubyやRailsというよりSQL寄り?
でもMySQLだとこれはエラーとなった。絶対何か他にいい方法あるよなぁ。
- 投稿日:2021-03-25T19:51:07+09:00
N + 1問題を解決する
はじめに仕込んでいたgem bulletが警告ログを発したので解決してみます。
N + 1問題とは?
データベースへのアクセス回数が必要以上に多くなってしまう現象の事。モデル間のアソシエーションで発生します。
gem bulletとは?
N + 1問題が発生してる箇所を警告で教えてくれるgemです。
現状
CareRecipitent Load (0.4ms) SELECT "care_recipitents".* FROM "care_recipitents" ↳ app/views/caregiver/tops/index.html.erb:1 Caregiver Load (0.5ms) SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] ↳ app/views/caregiver/tops/index.html.erb:37 CACHE Caregiver Load (0.0ms) SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] ↳ app/views/caregiver/tops/index.html.erb:37 CACHE Caregiver Load (0.0ms) SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] ↳ app/views/caregiver/tops/index.html.erb:37 Rendered caregiver/tops/index.html.erb within layouts/caregiver (Duration: 16.2ms | Allocations: 6553) CACHE Caregiver Load (0.1ms) SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]はじめに親モデルに検索がかけられ、その後に子モデルに4回クエリが発行されていることがわかります。
解決策
子モデル.includes(:親モデル)
def index #@caregiver = Caregiver.find(params[:staff_member_id]) - @care_recipitents = CareRecipitent.all + @care_recipitents = CareRecipitent.includes(:caregiver) endコントローラーのindexアクションを書き換えます。
CareRecipitent Load (1.2ms) SELECT "care_recipitents".* FROM "care_recipitents" ↳ app/views/caregiver/tops/index.html.erb:1 Caregiver Load (0.6ms) SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 [["id", 1]] ↳ app/views/caregiver/tops/index.html.erb:1 Rendered caregiver/tops/index.html.erb within layouts/caregiver (Duration: 75.3ms | Allocations: 19989) Caregiver Load (0.3ms) SELECT "caregivers".* FROM "caregivers" WHERE "caregivers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]クエリの回数が減り、無事ログを消えました。
- 投稿日:2021-03-25T17:54:56+09:00
repec 備忘録
導入方法
Gemfilegroup :development, :test do gem 'rspec-rails' #追加 gem 'capybara' #追加 #元あるやつはコメントアウトする endターミナル$ bundle install $ rails generate rspec:installspec/spec_helper.rb# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration require 'capybara/rspec' #追記 RSpec.configure do |config| config.before(:each, type: :system) do #追記 driven_by :rack_test #追記 end #追記 . . . config.include FactoryBot::Syntax::Methods #これを記入することでFactoryBot.create(:cake)⇒create(:cake)にできる config.include CartItemTestHelper #(helperはここに追加)初期設定
モデル、コントローラー作成時、関係するrspecのファイルを作成
config/application.rbconfig.generators do |g| g.test_framework :rspec, endテスト実行画面をいい感じにする
.rspec--require spec_helper --color --format dspec/support/配下のファイルを読み込む
(コメントアウト外す)/spec/rails_helper.rbDir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }ファイル作成方法
ファクトリーボット
ターミナル$ rails g factory_bot:model userテストファイル
ターミナル$ rails g rspec:system users $ rails g rspec:model user実行方法
ターミナル#どちらかで起動可能 $ rspec $ bundle exec rspec #特定の箇所のみ $ rspec spec/system/users_spec.rb $ rspec spec/system/users_spec.rb:2ファクトリーボット
表記方法
一意制約をもたせている場合は、email部のように表記するFactoryBot.define do factory :user do name {"test"} sequence(:email) { |n| "test#{n}@example.com"} password {"password"} end endモデルのテスト
require 'rails_helper' RSpec.describe CartItem, "モデルに関するテスト", type: :model do before do FactoryBot.create(:cake) FactoryBot.create(:candy) FactoryBot.create(:customer) end describe "実際に保存してみる" do it "有効な物は保存可能か?" do cart_item = CartItem.new(item_id: 1,customer_id: 1,amount: 2) expect(cart_item).to be_valid end context "空白のバリデーションチェック" do it "個数が空白" do cart_item = CartItem.new(item_id: 1,customer_id: 1,amount: "") expect(cart_item).to be_invalid expect(cart_item.errors[:amount]).to include("is not a number") end it "item_idが空白" do expect(FactoryBot.build(:cart_item, item_id: "")).to be_invalid #上記方法でもok end end end endフォームの入力
fill_in " idやname名 ", with: 入れたい内容 fill_in " idやname名 ", with: 入れたい内容 click_button " idやname名 "例
fill_in "customer_email", with: customer.email fill_in "customer_password", with: customer.password click_button "commit"helperの追加
helperの作成
spec/support/cart_item_test_helper.rbmodule CartItemTestHelper def item_in_cart(item, amount) visit item_path(item) fill_in "cart_item_amount", with: amount click_button "commit" end endspec_helperに追記
spec/spec_helper.rb# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration require 'capybara/rspec' RSpec.configure do |config| config.before(:each, type: :system) do driven_by :rack_test end . . . config.include FactoryBot::Syntax::Methods config.include CartItemTestHelper #追記
- 投稿日:2021-03-25T17:08:05+09:00
Rails6 Herokuにデプロイしようとしたらエラーが多発した話
前提
オリジナルアプリケーションを開発した後、herokuにデプロイした際にでたエラーを備忘録としてまとめておこうと思います。
結論
- assetのファイルの場所が違った
- bundlerのバージョンを合わせた
- platformを変えた
1つ目
% git heroku push master
実行すると、、、
. . . # 省略 Caused by: Sass::SyntaxError: File to import not found or unreadable: tagsinput. . . . remote: ! remote: ! Precompiling assets failed. remote: ! . . .と表示された。
tagsinput.jsが読み込まれていないとあるので、みてみるとrequire('../tagsinput')をjavastcript/packs/application.jsに記述していなかったのが原因だったっぽい。2つ目
1つ目のエラーが解消したので成功すると思い、
% git heroku push master
実行すると、、、
. . # 省略 . Bundler Output: Fetching gem metadata from https://rubygems.org/............ Your bundle is locked to mimemagic (0.3.5), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the author of mimemagic (0.3.5) has removed it. You'll need to update your bundle to a version other than mimemagic (0.3.5) that hasn't been removed in order to install. remote: ! remote: ! Failed to install gems via Bundler. remote: ! . . .調べてみたところ、ローカルのbundlerとherokuのbundlerを合わせないといけないらしい、、、
ということでもう一度Terminalを眺めてみると、Installing bundler 2.2.11
と書いてある
一方ローカルの方でみてみると% bundler -v Bundler version 2.1.4
違っていたので、ローカルの方を合わせることにした。
手順としては、
1. 今のローカルにあるbundlerをアンインストール。
2. Herokuに合わせたbundlerのversionをインストール
3. Gemfile.lockを一度削除。
4. Gemfile.lockを再度生成。
5. HerokuへPush
とういことでまず既存のbundlerをアンインストールするため% gem uninstall bundler
実行し、アンインストールができたら
バージョンを合わせるため、% gem install bundler --version '2.2.11'
を実行。
インストールできたことを確認したら、Gemfile.lockを削除するため下記を実行。% rm gemfile.lock
できたら、もう一度Gemfile.lockを生成するためバージョンを指定して下記を実行
% bundle _2.2.11_ install --without production
これでこのエラー解消できた!、、、
3つ目
と思いきやherokuにpushするとさらに追撃が、、、
. . # 省略 . Bundler Output: Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform is x86_64-linux. Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again. remote: ! remote: ! Failed to install gems via Bundler. remote: ! . . .エラー文に記載された通り、
% bundle lock --add-platform x86_64-linux
実行し、コミットしてプッシュする。
再度% git push heroku master
実行すると、やっとできた!
少しでも参考になったら幸いです。
参考
- 投稿日:2021-03-25T16:55:41+09:00
【jQuery Raty】ブラウザバックすると星が倍になる不具合
はじめまして、プログラミングを初めて3ヶ月の初学者です。
Ratyを利用した星評価を実装中に
ブラウザバックで星評価のある画面に戻ると
5つの星が10個になるという不具合にぶつかりました。いくら検索しても解決せず、最終的にメンターと試行錯誤して解決したので
今日は同じ目に逢ってる方と、いつかの自分の為に記録します。ちなみに初めて書くのでお手柔らかに…
目次
- 開発環境
- 不具合
- 何故なるのか?
- 結論 ←ココが解決策
- 解説
- 試した方法
開発環境
- Cloud9
- ruby '2.6.3'
- Rails 5.2.4.5
- jquery
不具合
本来5つ星での評価をしたいのに、
ブラウザバックで評価の存在するページに戻ると
星の数が倍になる
何故なるのか?
不具合時のコードを見ると記載がこうなります。
show.html.erb<div id="star-rate-<%= @review.id %>"></div> <script> $('#star-rate-<%= @review.id %>').raty({ size: 36, starOff: '<%= asset_path('star-off.png') %>', starOn : '<%= asset_path('star-on.png') %>', starHalf: '<%= asset_path('star-half.png') %>', readOnly: true, score: <%= @review.rate %>, }); </script>これだと、ページを表示する度に星5つを読み込むことになるとか…
順序で見てみると
- 星5つが読み込まれたページを表示
- ページ移行
- ブラウザバック
- 星5つが読み込まれたページ に 再度星5つ読み込む(合計10個になる)
となるのだとか…
つまり星10個の時点で他のベー時に移行し、再度ブラウザバックすると星が15個になってしまうわけです。
結論
ページを表示する際に、一度真っさらにしてしまえばいい。
先ほどのコードに1文追加するだけです。show.html.erb<script> $('#star-rate-<%= @review.id %>').empty(); #これを追加 $('#star-rate-<%= @review.id %>').raty({ size: 36, starOff: '<%= asset_path('star-off.png') %>',解説
これについては私もメンターの言葉を鵜呑みにしていたので、調べてみました。
【jQuery】要素を削除する.remove()と.empty()の違い
こちらの記事によると…empty();
こちらは指定した要素の中にある子要素を削除します。とのことでした。
メンターの言葉を借りると
星部分を一度削除→再度読み込む。
となるそうです。
試した方法
ついでなので、調べて試してダメだった方法も載せておきます。
.remove();
これだと親要素(星5つを表示するブロック)ごと削除されてしまうらしく
星5つを表示すらされませんでした。
周りでも数人同じことで困っていたので、結構よくあるのだと思います。
この記事が役に立ちます様に。
- 投稿日:2021-03-25T16:55:41+09:00
【Rails jQuery Raty】ブラウザバックすると星が増える不具合
はじめまして、プログラミングを初めて3ヶ月の初学者です。
Ratyを利用した星評価を実装中に
ブラウザバックで星評価のある画面に戻ると
星5個が星10個になるという不具合にぶつかりました。いくら検索しても解決せず、最終的にメンターと試行錯誤して解決したので
今日は同じ目に逢ってる方と、いつかの自分の為に記録します。ちなみに初めて書くのでお手柔らかに…
目次
- 開発環境
- 不具合
- 何故なるのか?
- 結論 ←ココが解決策
- 解説
- 試した方法
開発環境
- Cloud9
- ruby '2.6.3'
- Rails 5.2.4.5
- jquery
不具合
本来5つ星での評価をしたいのに、
ブラウザバックで評価の存在するページに戻ると
星の数が倍になる
何故なるのか?
不具合時のコードを見ると記載がこうなります。
show.html.erb<div id="star-rate-<%= @review.id %>"></div> <script> $('#star-rate-<%= @review.id %>').raty({ size: 36, starOff: '<%= asset_path('star-off.png') %>', starOn : '<%= asset_path('star-on.png') %>', starHalf: '<%= asset_path('star-half.png') %>', readOnly: true, score: <%= @review.rate %>, }); </script>これだと、ページを表示する度に星5つを読み込むことになるとか…
順序で見てみると
- 星5つが読み込まれたページを表示
- ページ移行
- ブラウザバック
- 星5つが読み込まれたページ に 再度星5つ読み込む(合計10個になる)
となるのだとか…
つまり星10個の時点で他のベー時に移行し、再度ブラウザバックすると星が15個になってしまうわけです。
結論
ページを表示する際に、一度真っさらにしてしまえばいい。
先ほどのコードに1文追加するだけです。show.html.erb<script> $('#star-rate-<%= @review.id %>').empty(); #これを追加 $('#star-rate-<%= @review.id %>').raty({ size: 36, starOff: '<%= asset_path('star-off.png') %>',解説
これについては私もメンターの言葉を鵜呑みにしていたので、調べてみました。
【jQuery】要素を削除する.remove()と.empty()の違い
こちらの記事によると…empty();
こちらは指定した要素の中にある子要素を削除します。とのことでした。
メンターの言葉を借りると
星部分を一度削除→再度読み込む。
となるそうです。
試した方法
ついでなので、調べて試してダメだった方法も載せておきます。
.remove();
これだと親要素(星5つを表示するブロック)ごと削除されてしまうらしく
星5つを表示すらされませんでした。
周りでも数人同じことで困っていたので、結構よくあるのだと思います。
この記事が役に立ちます様に。
- 投稿日:2021-03-25T16:31:22+09:00
【初学者向け】uninitialized constantエラー
uninitialized constantエラーが起きる原因
uninitialized constant errorを直訳すると「初期化されていない定数のエラー」という意味
Railsでは「定数やclassが定義されていない」ことを意味
uninitialized constantは名前が間違っているという意味のNameErrorということ
つまり、ファイル名の記述間違いなどで、呼びたいクラス名を記述出来ていない場合などでエラーが発生します。実際に出たエラー
NameError in Users::RegistrationsController#create
uninitialized constant User::GenderIdここから考えたこと
う〜んUser::GenderIdでエラーが発生してるみたいだから、GenderIdに関わる内容を確認してみたほうがよさそうだな。Railsでは「定数やclassが定義されていない」ことを意味する。。。ということはclass名やモデル名で定義しないといけないところをGenderIdで定義しているのでは。。。おっ!!
原因
user.rb(省略) extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :gender_id (省略)アソシエーションを間違えていたみたいです。。。
アソシエーションはテーブル同士で関連付けておき、一方のモデルからもう一方のモデルにアクセスできるようへするためのものなので、
今回の場合だと「GenderIdにアクセスしようとしたけどそんなものないですよ」と伝えてくれていたみたいです。 ⬅︎ という認識であってます??user.rb(省略) extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :gender (省略)上記のように編集したことで解決しました!!(Genderは定義されているので)
完全な凡ミスでした。。。参考
- 投稿日:2021-03-25T16:18:51+09:00
RailsのGPL混入問題についてまとめ(mimemagic)
!!New!!mimemagicがMITに戻った(3/26追記)
概要
RailsのGPL混入問題についてまとめました。間違いがあればご指摘ください。(2021/3/25現在)
https://github.com/rails/rails/issues/41750ここには3つの問題がある。
- Railsが依存しているmimemagicのライセンスがMITからGPL2.0になった
- もともとGPLライセンスのものが混入していたのにMITになってしまっていた
- これにより、Railsのbuildができなくなった
- Railsが依存しているmimemagic0.3.5が削除されたことが原因
- Railsの依存モジュールにGPLライセンスのものが混入することとなった
- mimemagicを0.3.6以降にすればbuildはできるが、GPL問題は解決しない
mimemagicのライセンスがMITからGPL2.0になった
mimemagicはMITからGPLに変わった。
mimemagicのissues #97によると、shared-mime-infoはGPLライセンス。
mimemagicの以下のファイルがshared-mime-info依存している。
https://github.com/minad/mimemagic/blob/master/script/freedesktop.org.xmlこれまでmimemagicはMITだったが、shared-mime-infoがGPLなので、mimemagicもGPLにすべきであり修正された。
変更内容:https://github.com/minad/mimemagic/commit/c0f7b6b21a192629839db87612794d08f9ff7e88Railsがbuildできない問題
前述のGPL問題修正により、Railsのbuildができない問題が起きた。
https://github.com/minad/mimemagic/issues/98
bundle install
すると以下のエラーが発生する。Installing dependencies using bundler 2.2.1 Running: bundle install --jobs=4 --retry=4 Your bundle is locked to mimemagic (0.3.5), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the author of mimemagic (0.3.5) has removed it. You'll need to update your bundle to a version other than mimemagic (0.3.5) that hasn't been removed in order to install.Railsが依存しているmiemagicは0.3.5。これが
but that version could not be found
と言われる。削除されたみたい。Railsの依存モジュールにGPLライセンス混入
0.3.6以上にすればbuildはできるようになるみたいだが、0.3.6も0.4.0もGPLなのでライセンス問題は解決されない。
GPLのソフトウェアをサーバサイドで使う場合の著作権表示について
GPLのソフトウェアをサーバサイドで使う場合の著作権表示について
GPLのライブラリをサーバサイドで使う場合、ソースコード公開義務はないという解釈が一般的です。
「サーバサイドで使えばプログラムの頒布じゃないからソースコード公開しなくていいじゃん!」という解釈のもと、ウェブサービスではGPLものが結構使われています。
どういうことかというと、ウェブサービスはプログラムの出力結果の頒布であって、プログラムの頒布ではないのでソースコードの公開義務はないという解釈です。
GCCでコンパイルされたバイナリを頒布してもソース公開義務がないのと同じ解釈です。という解釈があるようだが、どうなんだろうか。
リンク
mimemagicがMITに戻った(3/26追記)
mimemagicの修正PR:Externalise source data #3
this PR removes it from the gem, and instead requires the user to provide one themselves.
Otherwise an environment variable will need to be set to point it in the right direction.mimemagicに含まれるshared-mime-infoがGPL2.0だっため、これを取り除いたことによって、MITになった。
しかし、それを自分でインストールしないといけなくなった。
Place the file
freedesktop.org.xml
in an appropriate location, and then set the environment variableFREEDESKTOP_MIME_TYPES_PATH
to that path.How to fix
shared-mime-infoのインストール
shared-mime-info => MIME typesのデータベース。これがGPL2.0。
http://ftp.riken.jp/Linux/cern/centos/7/updates/x86_64/repoview/shared-mime-info.htmlLinux
Linuxならshared-mime-infoはインストールされてるみたい。CentOS7ではインストールされていた。
$ yum list installed | grep shared-mime-info shared-mime-info.x86_64 1.8-5.el7 @centos-basemacOS
shared-mime-infoをインストールする。
$ brew install shared-mime-info $ bundle update mimemagicもしmimemagicのupgradeだけで動かない人は、nokogiriとmarcelもupgradeするといいかも。
参照:https://github.com/rails/rails/issues/41757#issuecomment-806938727$ bundle update nokogiri marcel mimemagicmimemagicを0.3.9にupgrade
$ bundle update mimemagic$ git diff diff --git a/Gemfile.lock b/Gemfile.lock index cef0127..4a0ef93 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -133,7 +133,9 @@ GEM marcel (0.3.3) mimemagic (~> 0.3.2) method_source (1.0.0) - mimemagic (0.3.5) + mimemagic (0.3.9) + nokogiri (~> 1) + rake mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.3)shared-mime-infoのPATHを環境変数にセット
PATHは以下のあたりにある。参考:possible_paths
- /usr/local/share/mime/packages/freedesktop.org.xml
- /opt/homebrew/share/mime/packages/freedesktop.org.xml
- /usr/share/mime/packages/freedesktop.org.xml
CentOS7では以下にあった。
$ ls -l /usr/share/mime/packages/freedesktop.org.xml -rw-r--r-- 1 root root 2196823 Apr 1 2020 /usr/share/mime/packages/freedesktop.org.xmlRails起動時にこれを環境変数
FREEDESKTOP_MIME_TYPES_PATH
としてセットする。$ FREEDESKTOP_MIME_TYPES_PATH=/usr/share/mime/packages/freedesktop.org.xml \ bundle exec pumactl start一応これで起動したし、問題はなさそうに見える。
これでよいのかrailsのIssueで聞いてみてる。(3/26 12:00現在)
https://github.com/rails/rails/issues/41757#issuecomment-807898051
- 投稿日:2021-03-25T16:18:51+09:00
RailsのGPL混入問題についてまとめ
!!New!!mimemagicがMITに戻った(3/26追記)
概要
RailsのGPL混入問題についてまとめました。間違いがあればご指摘ください。(2021/3/25現在)
https://github.com/rails/rails/issues/41750ここには3つの問題がある。
- Railsが依存しているmimemagicのライセンスがMITからGPL2.0になった
- もともとGPLライセンスのものが混入していたのにMITになってしまっていた
- これにより、Railsのbuildができなくなった
- Railsが依存しているmimemagic0.3.5が削除されたことが原因
- Railsの依存モジュールにGPLライセンスのものが混入することとなった
- mimemagicを0.3.6以降にすればbuildはできるが、GPL問題は解決しない
mimemagicのライセンスがMITからGPL2.0になった
mimemagicはMITからGPLに変わった。
mimemagicのissues #97によると、shared-mime-infoはGPLライセンス。
mimemagicの以下のファイルがshared-mime-info依存している。
https://github.com/minad/mimemagic/blob/master/script/freedesktop.org.xmlこれまでmimemagicはMITだったが、shared-mime-infoがGPLなので、mimemagicもGPLにすべきであり修正された。
変更内容:https://github.com/minad/mimemagic/commit/c0f7b6b21a192629839db87612794d08f9ff7e88Railsがbuildできない問題
前述のGPL問題修正により、Railsのbuildができない問題が起きた。
https://github.com/minad/mimemagic/issues/98
bundle install
すると以下のエラーが発生する。Installing dependencies using bundler 2.2.1 Running: bundle install --jobs=4 --retry=4 Your bundle is locked to mimemagic (0.3.5), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the author of mimemagic (0.3.5) has removed it. You'll need to update your bundle to a version other than mimemagic (0.3.5) that hasn't been removed in order to install.Railsが依存しているmiemagicは0.3.5。これが
but that version could not be found
と言われる。削除されたみたい。Railsの依存モジュールにGPLライセンス混入
0.3.6以上にすればbuildはできるようになるみたいだが、0.3.6も0.4.0もGPLなのでライセンス問題は解決されない。
GPLのソフトウェアをサーバサイドで使う場合の著作権表示について
GPLのソフトウェアをサーバサイドで使う場合の著作権表示について
GPLのライブラリをサーバサイドで使う場合、ソースコード公開義務はないという解釈が一般的です。
「サーバサイドで使えばプログラムの頒布じゃないからソースコード公開しなくていいじゃん!」という解釈のもと、ウェブサービスではGPLものが結構使われています。
どういうことかというと、ウェブサービスはプログラムの出力結果の頒布であって、プログラムの頒布ではないのでソースコードの公開義務はないという解釈です。
GCCでコンパイルされたバイナリを頒布してもソース公開義務がないのと同じ解釈です。という解釈があるようだが、どうなんだろうか。
リンク
mimemagicがMITに戻った(3/26追記)
mimemagicの修正PR:Externalise source data #3
this PR removes it from the gem, and instead requires the user to provide one themselves.
Otherwise an environment variable will need to be set to point it in the right direction.mimemagicに含まれるshared-mime-infoがGPL2.0だっため、これを取り除いたことによって、MITになった。
しかし、それを自分でインストールしないといけなくなった。
Place the file
freedesktop.org.xml
in an appropriate location, and then set the environment variableFREEDESKTOP_MIME_TYPES_PATH
to that path.How to fix
shared-mime-infoのインストール
shared-mime-info => MIME typesのデータベース。これがGPL2.0。
http://ftp.riken.jp/Linux/cern/centos/7/updates/x86_64/repoview/shared-mime-info.htmlLinux
Linuxならshared-mime-infoはインストールされてるみたい。CentOS7ではインストールされていた。
$ yum list installed | grep shared-mime-info shared-mime-info.x86_64 1.8-5.el7 @centos-basemacOS
shared-mime-infoをインストールする。
$ brew install shared-mime-info $ bundle update mimemagicもしmimemagicのupgradeだけで動かない人は、nokogiriとmarcelもupgradeするといいかも。
参照:https://github.com/rails/rails/issues/41757#issuecomment-806938727$ bundle update nokogiri marcel mimemagicmimemagicを0.3.9にupgrade
$ bundle update mimemagic$ git diff diff --git a/Gemfile.lock b/Gemfile.lock index cef0127..4a0ef93 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -133,7 +133,9 @@ GEM marcel (0.3.3) mimemagic (~> 0.3.2) method_source (1.0.0) - mimemagic (0.3.5) + mimemagic (0.3.9) + nokogiri (~> 1) + rake mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.3)shared-mime-infoのPATHを環境変数にセット
PATHは以下のあたりにある。参考:possible_paths
- /usr/local/share/mime/packages/freedesktop.org.xml
- /opt/homebrew/share/mime/packages/freedesktop.org.xml
- /usr/share/mime/packages/freedesktop.org.xml
CentOS7では以下にあった。
$ ls -l /usr/share/mime/packages/freedesktop.org.xml -rw-r--r-- 1 root root 2196823 Apr 1 2020 /usr/share/mime/packages/freedesktop.org.xmlRails起動時にこれを環境変数
FREEDESKTOP_MIME_TYPES_PATH
としてセットする。$ FREEDESKTOP_MIME_TYPES_PATH=/usr/share/mime/packages/freedesktop.org.xml \ bundle exec pumactl start一応これで起動したし、問題はなさそうに見える。
これでよいのかrailsのIssueで聞いてみてる。(3/26 12:00現在)
https://github.com/rails/rails/issues/41757#issuecomment-807898051
- 投稿日:2021-03-25T15:47:05+09:00
【Rails】ユーザー編集時だけパスワードのバリデーションを無効にする(devise)
環境
macOS: Big Sur Ver11.2.2
Rails: 6.0.0
Ruby: 2.6.5この記事の目標
devise のデフォルトのユーザー編集画面ではパスワードの変更ができるが、現在のパスワードを入力しないとユーザー情報が編集できないようになっている。
そこで、
①現在のパスワードを入力しなくてもユーザー情報ができるようにする
②ユーザー編集のときだけモデルに設定しているパスワードのバリデーションを解除し、パスワード変更欄が空欄のままでもユーザー編集ができるようにするの2点を実装することを目標とします。
現在のパスワードを入力不要にする
これについては多くの記事が出ています。以下が参考になります。
ユーザー編集時だけパスワードのバリデーションを解除する
まず、Userモデルのバリデーションは以下のとおり
app/models/user.rbclass User < ApplicationRecord has_many :menus extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :prefecture belongs_to :category has_one_attached :image # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable # パスワードは半角英数混合で8文字 validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i } with_options presence: true do validates :shop_name validates :address validates :business_hours validates :holiday validates :image validates :phone_number, format: { with: /\A0[1-9]\d{0,3}[-(]\d{1,4}[-)]\d{4}\z/ } with_options numericality: { other_than: 0, message: 'を選択してください' } do validates :category_id validates :prefecture_id end end end真ん中あたりにパスワードカラムのバリデーションに関する記述があり、正規表現を使っているため自動的に presence: true の存在性のバリデーションが効いています。
これは新規登録時には必須なのですが、編集時にパスワードを変えずに他の項目だけ変更したい場合にバリデーションエラーのもとになってしまいます。解決策(オプションを記述する)
上記のパスワードカラムに対するバリデーションに on: :create オプションを記述します。
これにより新規登録時のみバリデーションがかかるようになります!
参考:Railsガイド「onオプション」app/models/user.rbclass User < ApplicationRecord (略) # on: :createオプションを追記 validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i }, on: :create with_options presence: true do validates :shop_name validates :address validates :business_hours validates :holiday validates :image validates :phone_number, format: { with: /\A0[1-9]\d{0,3}[-(]\d{1,4}[-)]\d{4}\z/ } with_options numericality: { other_than: 0, message: 'を選択してください' } do validates :category_id validates :prefecture_id end end endただし、これではユーザー編集時にパスワードに関するバリデーション(今回は半角英数混合で8文字)がまったく効かなくなってしまい、「abc」とかでもパスワード設定できてしまいます。
そこで、今回はバリデーションの記述を2行に分け、allow_blank: true オプションを追記します。ということで、最終的なモデルのコードはこんな感じ。
app/models/user.rbclass User < ApplicationRecord has_many :menus extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :prefecture belongs_to :category has_one_attached :image # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable # パスワードに関するバリデーションをcreateとupdateで別々に記述しました validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i }, on: :create validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8}\z/i, message: 'は半角英数混合で8文字です' }, allow_blank: true, on: :update with_options presence: true do validates :shop_name validates :address validates :business_hours validates :holiday validates :image validates :phone_number, format: { with: /\A0[1-9]\d{0,3}[-(]\d{1,4}[-)]\d{4}\z/ } with_options numericality: { other_than: 0, message: 'を選択してください' } do validates :category_id validates :prefecture_id end end def update_without_current_password(params) if params[:password].blank? && params[:password_confirmation].blank? params.delete(:password) params.delete(:password_confirmation) end update(params) end endこれでユーザー編集時にパスワードの変更をしない場合は空欄のまま変更ができ、パスワードの変更をする場合は正規表現を適用することができました!
以上!
- 投稿日:2021-03-25T15:11:45+09:00
Active Storageで画像投稿とツイート機能を実装しようとしたらエラーになってしまいました
RailsでActive Storageを使って画像も投稿できるツイッターのようなものを作ろうとしていたのですが、それをしている途中でRouting Errorになってしまいました。
Routing Error No route matches [POST] "/posts/new"今回はその解決法と、投稿が表示される仕組みから今回どうしてエラーが解決できたのかを自分なりにまとめていきたいと思います。
エラーになってしまったcontrollerがあるのでそちらを見ていきたいと思います。
いかがそのcontrollerの部分のコードです。class PostsController < ApplicationController before_action :authenticate_user!, only: [:new, :update, :create, :edit, :update, :destroy] before_action :find_post, only: [:edit, :update, :show, :destroy] def index @posts = Post.all @like = Like.new end def new @like = Like.new end def show end def create @post = current_user @post = Post.create(post_params) if @post.save redirect_to root_path,notice:'投稿に成功しました' else redirect_to new_post_path,notice:'投稿に失敗しました' end end def edit end def update @post.update(post_params) end def destroy if @post.destroy redirect_to root_path,alert: '投稿を削除しました' else redirect_to root_path end end private def post_params params.require(:post).permit(:content, images: []).merge(user_id: current_user.id) end def find_post @post = Post.find(params[:id]) end def force_redirect_unless_my_post return redirect_to root_path,alert:'権限がありません'if @post.user != current_user end end
@like
などの物が入っていますが、それはいま高評価機能を作っているからそうなっています。
そして今回の原因なのですが、newメソッドの中にpostのnewメソッドというオブジェクトという今回でいうと投稿を作る機能を入れておく器を作るコードが書いていないからです。
当たり前ですがRailsは
Routing
→Controller
→model
→view
の順番で動いていきます。
ですが、仮にRoutingまで行けたとしても、そこから先のControllerで指定されたActionを用意できないとRouting errorになってしまいます。
ですので、正しいコードはこちらになります正しいコード
class PostsController < ApplicationController before_action :authenticate_user!, only: [:new, :update, :create, :edit, :update, :destroy] before_action :find_post, only: [:edit, :update, :show, :destroy] def index @posts = Post.all @like = Like.new end def new @post = Post.new @like = Like.new end def show end def create @post = current_user @post = Post.create(post_params) if @post.save redirect_to root_path,notice:'投稿に成功しました' else redirect_to new_post_path,notice:'投稿に失敗しました' end end def edit end def update @post.update(post_params) end def destroy if @post.destroy redirect_to root_path,alert: '投稿を削除しました' else redirect_to root_path end end private def post_params params.require(:post).permit(:content, images: []).merge(user_id: current_user.id) end def find_post @post = Post.find(params[:id]) end def force_redirect_unless_my_post return redirect_to root_path,alert:'権限がありません'if @post.user != current_user end endここの
newメソッドの中に注目してくださいdef new @post = Post.new @like = Like.new end
@post = Post.new
が加わっているので、投稿(post)のオブジェクトが作られています。
これにより、Routingで指定したアクションが用意されているのでエラーが解決できるわけです。
皆さん是非参考にしてみてください最後に
今回terateilさんで質問をして回答をしていただきました。
今回質問を回答していただいたので、その方のURLをはらせていただきます。
この場でお礼申し上げます
https://teratail.com/users/maisumakun#reply
- 投稿日:2021-03-25T15:11:31+09:00
Rails→Git→Heroku→サイト公開 〜手順〜
概要
Railsで作成したプロジェクトをデプロイしてサイト公開するまでの手順の解説
今回は公開の手順なので導入方法については明記していません。参考欄をご参照ください。
メモなので細かい事は書いてません。すいません。目次
・手順① プロジェクトの準備
・手順② Gitとの連携
・手順③ herokuとの連携環境
version etc PC 13-inch, m1, 2020 MacBookPro OS 11.2.3 Big Sur Rails 6.1.3 git 2.24.3 Apple Git-128 heroku 7.51.0 node-v12.21.0 bundler 2.1.4 手順① プロジェクトの準備
Railsで新規プロジェクトを作成
% rails new sample_app(← 任意の名前)終わると↓こんな感じ↓でケーキとクラッカーで祝福してくれる(笑)
├─ websocket-extensions@0.1.4 └─ ws@6.2.1 ✨ Done in 9.05s. Webpacker successfully installed ? ?
移動して確認してみると色々作ってくれてる。すごい!ハイテク!
% cd sample_app ~/sample_app master* % ls Gemfile app config.ru node_modules storage yarn.lock Gemfile.lock babel.config.js db package.json test README.md bin lib postcss.config.js tmp Rakefile config log public vendor続いてRailsサーバー起動! ちゃんと起動できるとしたみたいになる↓
~/sample_app master* % rails s => Booting Puma => Rails 6.1.3 application starting in development => Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.2.2 (ruby 2.7.2-p137) ("Fettisdagsbulle") * Min threads: 5 * Max threads: 5 * Environment: development * PID: 52125 * Listening on http://127.0.0.1:3000 * Listening on http://[::1]:3000 # localhost:3000 で開いてみ!って言われてる Use Ctrl-C to stop # わかってると思うけどサーバーを止める時は Ctrl + C を押せよって言われてる言われた通りブラウザで localhost:3000 を開くとなんか祝福されてる
手順② Gitとの連携
github アカウントの作成
下記リンクよりアカウントを作成してください。
リポジトリ作成
リポジトリをプライベートで新規作成してリポジトリができたらターミナルで下記を入力
% git init % git add . % git commit -m "first commit" % git remote add origin https://github.com/アカウント名/リポジトリ名.git % git push -u origin masterGitに更新をかけてみてリポジトリの内容が追加されていればOKです。
ついでによく使いそうなコマンドのエイリアスを作成しておきます。
.zshrcalias gs='git status' # 今いるブランチや追加などがあるか表示してくれる alias ga='git add .' # バージョン管理下に置く alias gc='git commit -m '$1 # コミットする 第1引数に文字列を送れるようにしてる。(関数にして色々やる方が便利) alias gp='git push' # プッシュする alias gb='git branch' # ブランチ一覧と自分のいるブランチを表示これでGitとの連携はOKですね!色々といじってみてください
手順③ Herokuとの連携
色々と準備
railsの基本データベースはSQlite3になっていると思うのですがherokuはPostgreSQLらしいのでGemfileを書き換えます。
Gemfileは作成プロジェクト内に入ってます。(左の -数値 は大体この位の行に書いてあるっていうのを明記しています。)////////// 下記2行を削除 /////////// -8 # Use sqlite3 as the database for Active Recor -9 gem 'sqlite3', '~> 1.4' ///////////////////////////////// -29 group :development, :test do -30 gem 'sqlite3', '1.4.2' # ← この一文を追加 /////////// -31 # Call 'byebug' anywhere in the code to stop execution and get a debugger console -32 gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] -33 end /////////// まるまる追加[追加する行はどこでも大丈夫です] /////////// -54 group :production do -55 gem 'pg', '1.1.4' -56 end /////////////////////////////////できたらこれをGemfile.lockに反映させるので下記を実行。じゃないとherokuにデプロイした時にエラー吐きます。(自分は結構忘れがちになるのでエラーだいぶ吐かれました)
% bundle install --without production実行完了したらこんなんでました。
Bundle complete! 18 Gemfile dependencies, 75 gems now installed. Gems in the group production were not installed. Use `bundle info [gemname]` to see where a bundled gem is installed.変更内容をgitにも反映させておきましょう!(やり方は手順②を参考に)ここでエイリアスためしてみてね。
まちにまったheroku
% heroku --version
でバージョン表示されない方はherokuをインストールしてくださいな。
ちゃんとバージョンが表示されるよになったら heroku にログインします。(アカウントがない方は作成してね。無料ね。)
ログイン方法は好きなほうで大丈夫です。% heroku login # ブラウザが立ち上がってログイン画面が出るってよ % heorku login --interactive # ターミナルのままログイン情報打ち込めるってよログイン完了するとターミナルに下記画面が表示されます。
Logging in... done Logged in as 自分のアカウントのメールアドレスそしたらherokuに新規アプリケーション(プロジェクト)を作成しまする。
% heroku create完了するとこんなんでました。適当にアプリ名を考えて作成してくれます。
Creating app... done, ⬢ [適当な数値と文字列] https://[適当な数値と文字列].herokuapp.com/ | https://git.heroku.com/[適当な数値と文字列].githerokuapp.com/のURLを打ち込むともうサイトができてますね!
そうですあとはここにGitを反映させるだけですね!
それでは魔法の呪文を打ち込みます。% git push heroku masterそうするとターミナルにババババババと出てきて色々してくれます。
初回のみRailsをインストールするので時間がちょっとかかるかもしれないですね。
完了すると、、、reemote: https://[適当な数値と文字列].herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done. To https://git.heroku.com/[適当な数値と文字列].git * [new branch] master -> masterと完了したみたいなのでherokuapp.com/のURLにアクセスします。
みんなが祝福してくれたあの微笑ましい画像が出ると思ってました。。
ってことで元のプロジェクトの方で適当に書いていきます。application_controller.rbclass ApplicationController < ActionController::Base def hello render html:"hello, ruby on rails" end endroutes.rbRails.application.routes.draw do root 'application#hello' endこれでgitとherokuにまたaddしてcommitしてpushします。
完了したらまた herokuapp.com にアクセスしてみます。hello, ruby on rails
と表示されていればOKですね!
無事サイト公開までいきました!でめたし!でめたし!応用編
git push で heroku を更新や 独自ドメインの設定方法など記載しました。
Rails→Git→Heroku→サイト公開 〜応用〜参考
Ruby on Rails チュートリアル
【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】
- 投稿日:2021-03-25T15:10:59+09:00
Rails→Git→Heroku→サイト公開 〜応用〜
前記事
Railsプロジェクトの作成からGitにpushからherokuにデプロイの手順の解説してます。
Rails → Git → Heroku → サイト公開 〜手順〜
目次
・応用① git push で heroku も反映
・応用② 独自ドメイン使いたくね?応用① git push で heroku も反映
gitにpushしたらherokuも自動的に変わって欲しいと思ったのでherokuのdeploy画面にいきます。
選択すると↓画面みたくなるので repo name のところに自分のgitのリポジトリ名を入力
そうすると下の方に自分のリポジトリ名が出てくるのでconnectionみたいなやつを押す
無事連携できると↓画面みたくなるので Enable Automatic Deploys をクリック
確認のためコード編集
application_controller.rbclass ApplicationController < ActionController::Base def hello render html:"hello, ruby on rails / git and heroku" end end編集したら git の方だけで add して commit して push!!
これ一連でやってくれるコマンドあるんで気になる方は調べてみてね。ちょっと待機・・・(git pushはすぐ終わるけど heroku へのデプロイはちょっと時間かかる。20秒位?)
そんでherokuapp.comのURLを確認
hello, ruby on rails / git and heroku
って表示されたらOKです!無事gitのpushだけでサイトに反映できました。
「gitにpushしただけで反映されたら困るよー」って方は
解除するなり、別ブランチにデプロイしてmasterにpullするなりなんなりしてくださいな。
はい!次!応用② 独自ドメイン使いたくね?
って事なんですけど、無料じゃできないみたいです。
なのでここからは有料でもいいよって方だけみてください。
って言っても $7/month のプランに切り替えるだけです。
切り替えは Resources から Change Dyno Type を Free から Hobby に変更すれば良いだけです。
詳しい DynoType については公式で → Heroku Dynos肝心のドメインは お名前ドットコム でドメインを取得して反映させます。
ドメインの取得はこちらを参考に → ドメイン取得方法好きなドメインを取得したらherokuに登録します。今回はサンプルで test-sample.com で書いていきます。
なので test-sample.com のところを自分で取得したドメイン名に置き換えてくださいな。% heroku domains:add test-sample.comちゃんと登録できると
Configure your app's DNS provider to point to the DNS Target [ランダムな数値とアルファベット].herokudns.com. For help, see https://devcenter.heroku.com/articles/custom-domains The domain test-sample.com has been enqueued for addition Run heroku domains:wait 'test-sample.com' to wait for completion Adding test-sample.com to ⬢ [自分のherokuのAPP名]... doneDNS Targetは後ほど使います。
次にheorkuのResouces画面からAdd-onsで 「PointDNS」を検索して追加します。
そうすると↓の画像みたいにると思うので
そのPointDNSを選択します。
domain name ってところに取得したドメインを入力
色々出てくるので + Add record をクリック
ここで諸々記入していきます。Record type : CNAMEに変更します。
Name : www
Hostname : DNS Targetを入力これでAdd recordすればOKです。
ここで Type NS っていうのが4つくらいあるかと思うんですがこれを
お名前ドットコムのほうで使用します。
この画面に移動すると思うので
ホスト名 : www
Type : CNAME に変更
VALUE : DNS Targetを入力追加で追加します。
追加されたら設定を忘れずにおこないましょう。
「DNSレコード設定用ネームサーバー変更確認」はチェックを入れずに確認画面に進み設定します。一応ネームサーバも設定します。
自分のドメインを選択し、その他のネームサーバーを使うを選択
ネームサーバ1、2、3、4 に
先程のPointDNSの4つの Type NS のやつのDataだけをコピペしていきます。
末尾が com. となっていたら . は消してください。
全て入力したら確認を押します。これで終了です。
ちょっと待機・・・(反映はすぐにはされません。30分くらいは待ったかな?)
気長に待ちましょう。WWW.自分のドメイン名 でherokuと同じページが出たら無事独自ドメインで反映されています。
おわりに
結構反映されないと不安ですが気長に待ちましょう。
ちょっと大変ですが、レンタルサーバー借りて色々やるよりかなりコストカットできると思います。
反映されればsslも簡単に設定できます。
- 投稿日:2021-03-25T14:40:57+09:00
seedで10人ユーザーを作って1人5つの記事を持たせるユーザーを作成する
開発環境
環境
ruby:2.6.4
rails:6.0.3
userにはusersモデル、username,email,password,password_confirmation(確認用)を持たせ、
投稿にはarticlesモデル、title,textカラムを持たせています。
画像のアップロードはactivestorageを使用してavatarとしています。
gem 'Faker'を使用しています。題名の通り早速作っていきます
アカウント=10人
1人のアカウント=5つのarticle(記事)
Faker::Name.nameはランダムに名前を作成してくれるfakerの機能、
Faker::Internet.emailはランダムにemailを作成してくれる機能、
Faker::Hacker.say_something_smartはランダムで文字を作成してくれる機能だと思います。
これに関してはあまり理解しておらずとりあえず文字を作成してくれたので使用しています
指定の文字を入れたい場合は
titel: "任意の文字"
text: "任意の文字"
とすれば良いと思います。
avatarには/assets/imagesに保存してある画像を登録するようにしてあります。seed.rbputs 'users ...' 10.times do user = User.create!( username: Faker::Name.name, email: Faker::Internet.email, password: 'foobar', password_confirmation: 'foobar', ) user.avatar.attach(io: File.open('app/assets/images/cat.jpg'),filename: 'cat.jpg') end puts 'articles ...' 5.times do |n| User.all.each do |user| user.articles.create!( title: Faker::Hacker.say_something_smart, text: Faker::Hacker.say_something_smart ) end enduser.avatar.attach(io: File.open('app/assets/images/cat.jpg'),filename: 'cat.jpg')上のavatarを登録するコードですが必ず()の外で書くようにしてください。
()の中で書くと誤字のエラーがでます。僕はこのエラーに5時間ほどハマりました。
それにactivestorageの場合あまり情報が少ないので本当にこの記述で正解なのかもわかりませんがとりあえず成功できているので良いと思います。
これで内容がよければrails db:seedと打てば完了になります。
最後にいつでもログインできるアカウントを作る
migrate:resetしたときにいちいちアカウントを作り直すのもめんどくさいのでseedにいつでもログインできるようにメール認証もいらないアカウントを作ります。
人気俳優のお二人に参加してもらいます。
user1.skip_confirmation!
これはメール認証はスキップするコードみたいです。
しかしこのまま実行するとアカウント作成は成功したもののメール認識のスキップはできていませんでした。
そこで最後に
user1.save!と保存し、実行してみると見事成功していました。
今回は画像を保存するのは面倒だったのでコードは書きませんでしたが上と同じようにすることでできるかと思います。seed.rbuser1 = User.create!( username: "横浜流星", email: "任意のアドレス", password: '123456', password_confirmation: '123456', ) user1.skip_confirmation! user1.save! user2 = User.create!( username: "成田凌", email: "任意のアドレス", password: 'abcdef', password_confirmation: 'abcdef', ) user2.skip_confirmation! user2.save!rails初学者が書いた記事なので間違いがあるかもしれません
もし間違いがある場合報告してもらえますと助かります。
- 投稿日:2021-03-25T14:03:15+09:00
ローカルでのエラーAccess denied for user 'root'@'localhost' (using password: NO)が出たとき。
・エラー:Access denied for user 'root'@'localhost' (using password: NO)
・問題は『PWがないので開かない。』ということです。
・解決方法
・root ユーザーのPW設定を無くして、rails sで動くようにする。
・mysqlで設定したパスワードをdatabase.ymlに書く。・手順
・mysqlの起動
sudo service mysql start・mysqlにログイン
mysql -u root -p・使用するデータベースを選択する。
mysql> use mysql;・パスワードを空にする。
mysql> update user set authentication_string='' where user='root';
・変更が成功したらmysqlを閉じる。
mysql> exit・変更を反映させるため、,mysqlをストップ。
sudo service mysql stop・再び起動。
sudo service mysql start・パスワードなしで、ログインできることを確認。
mysql -u root・rails s 立ち上げる(rails s をしていた場合は一度閉じてからもう一度立ち上げる)。
以上、お疲れ様で〜〜〜す。
- 投稿日:2021-03-25T12:53:48+09:00
README 画像挿入の仕方
README 画像挿入
Qiita記事では多くのREADMEについての画像の挿入の手順を解説している記事があります。
今回私は、上記記事でのやり方とは違った、googleの拡張機能を使用した画像作成・READMEに画像挿入までの手順を解説します!!というのも、閲覧記事で参考になったものは多くありましたが、googleの拡張機能を使用した画像挿入についての記事は、調べたところでは見当たらなかったので、
自身で挿入から、解決まで行いました。ご参考までにしていただけたら幸いです。
なぜ他記事を参考にしなかったか
今回、自身で作成したポートフォリオでは、トップページだけでもかなり下にスクロールして全体像が見えるという、課題がありました。
通常のスクリーンショットでは、一画面に収まりせんでした。
gif画像でもgyazoを使用して全体を撮影することも実行しましたが、
撮影秒数が決められたなか全てを撮影するのは困難且、見にくい画像となってしまいました。そこでgoogle拡張機能の「Awesome Screenshot」を使用し、全体を撮影できるようにしました。
Awesome Screenshot
googleの検索で「Awesome Screenshot 拡張機能」と検索していただいたらでききます。
インストールを行ったら順位完了です!Awesome Screenshotではフルページ画像がとる事ができ、非常に使い勝手が便利な拡張機能となっています。
画像撮影手順
インストールしたAwesome Screenshotを撮影したいHPでクリックします。
1.クリック後上部バーで「レコード」「キャプチャ」の選択蘭があるので、「キャプチャ」をクリック
2.「キャプチャ」をクリックしたら、「フルページ」をクリック
3.「フルページ」をクリック後、自動でページを撮影できます
4.撮影した画像をダウンロードして完了
非常に簡単な手順でフルページの撮影ができるのでおすすめです!!
READMEに画像情報記載
ダウンロードした画像を、自身の開発中コードのディレクトリに挿入します。
※画像専用のディレクトリを作成しておくことをおすすめします私の場合、ダウンロードした画像を
public/imagesディレクトリに格納しています。後は、格納した画像をREADMEに記述するだけで画像挿入ができます。
<img src="public/images/画像名">まとめ
非常に簡単に且フルページでの画像挿入ができるので、スクリーンショットで何枚も画像をとる手間を省けます!!
今回掲載した内容は他のqiita記事には調べた限りなかった為、
共有させていただきます!!issueを利用した画像挿入の仕方もあるので、その際は他の記事にも乗っているのでそちら参考にしていただけたらと思います!!
宜しくお願いします。
- 投稿日:2021-03-25T12:21:45+09:00
Ruby on Railsの日付操作まとめ
現在日付/時刻
pry(main)> Time.current => Thu, 25 Mar 2021 11:36:35 JST +09:00 pry(main)> 0.days.ago => Thu, 25 Mar 2021 12:16:53 JST +09:00nowよりcurrentを使うほうが良いらしい。
https://qiita.com/kodai_0122/items/111457104f83f1fb2259特定の日付
pry(main)> Time.new(2021, 3, 25, 11, 22, 33, 00) => 2021-03-25 11:22:33 +0000●日前/●日後
[9] pry(main)> Time.current.yesterday => Wed, 24 Mar 2021 11:47:08 JST +09:00 [10] pry(main)> Time.current.tomorrow => Fri, 26 Mar 2021 11:47:16 JST +09:00 [11] pry(main)> Time.current.ago(3.days) => Mon, 22 Mar 2021 11:47:28 JST +09:00 [12] pry(main)> Time.current.since(3.days) => Sun, 28 Mar 2021 11:47:43 JST +09:00 [13] pry(main)>●ヶ月前/●ヶ月後
[13] pry(main)> Time.current.last_month => Thu, 25 Feb 2021 11:50:33 JST +09:00 [14] pry(main)> Time.current.next_month => Sun, 25 Apr 2021 11:50:41 JST +09:00 [15] pry(main)> Time.current.ago(3.month) => Fri, 25 Dec 2020 11:50:52 JST +09:00 [16] pry(main)> Time.current.since(3.month) => Fri, 25 Jun 2021 11:50:59 JST +09:00 [17] pry(main)>●年前/●年後
[17] pry(main)> Time.current.last_year => Wed, 25 Mar 2020 11:52:07 JST +09:00 [18] pry(main)> Time.current.next_year => Fri, 25 Mar 2022 11:52:12 JST +09:00 [19] pry(main)> Time.current.ago(3.year) => Sun, 25 Mar 2018 11:52:26 JST +09:00 [20] pry(main)> Time.current.since(3.year) => Mon, 25 Mar 2024 11:52:34 JST +09:000:00/23:59
[23] pry(main)> Time.current.beginning_of_day => Thu, 25 Mar 2021 00:00:00 JST +09:00 [24] pry(main)> Time.current.end_of_day => Thu, 25 Mar 2021 23:59:59 JST +09:00月初/月末
[25] pry(main)> Time.current.beginning_of_month => Mon, 01 Mar 2021 00:00:00 JST +09:00 [26] pry(main)> Time.current.end_of_month => Wed, 31 Mar 2021 23:59:59 JST +09:00年始/年末
[27] pry(main)> Time.current.beginning_of_year => Fri, 01 Jan 2021 00:00:00 JST +09:00 [28] pry(main)> Time.current.end_of_year => Fri, 31 Dec 2021 23:59:59 JST +09:00週明け/週末
[29] pry(main)> Time.current.beginning_of_week => Mon, 22 Mar 2021 00:00:00 JST +09:00 [30] pry(main)> Time.current.end_of_week => Sun, 28 Mar 2021 23:59:59 JST +09:00先週/来週(何故か時間は月曜0:00になるよう・・・)
[31] pry(main)> Time.current.last_week => Mon, 15 Mar 2021 00:00:00 JST +09:00 [32] pry(main)> Time.current.next_week => Mon, 29 Mar 2021 00:00:00 JST +09:00●曜日
[38] pry(main)> Time.current.beginning_of_week(:wednesday) => Wed, 24 Mar 2021 00:00:00 JST +09:00 [39] pry(main)> Time.current.last_week(:wednesday) => Wed, 17 Mar 2021 00:00:00 JST +09:00 [40] pry(main)> Time.current.next_week(:wednesday) => Wed, 31 Mar 2021 00:00:00 JST +09:00フォーマット
[41] pry(main)> Time.current.strftime("%Y-%m-%d %T") => "2021-03-25 12:09:26"
範囲
範囲をwhere句に渡すとbetweenで検索してくれるらしい[50] pry(main)> Time.current.all_day => Thu, 25 Mar 2021 00:00:00 JST +09:00..Thu, 25 Mar 2021 23:59:59 JST +09:00 [51] pry(main)> Time.current.all_month => Mon, 01 Mar 2021 00:00:00 JST +09:00..Wed, 31 Mar 2021 23:59:59 JST +09:00 [52] pry(main)> Time.current.all_year => Fri, 01 Jan 2021 00:00:00 JST +09:00..Fri, 31 Dec 2021 23:59:59 JST +09:00
- 投稿日:2021-03-25T11:44:22+09:00
【AWS】EC2へのデプロイ時にmimemagicのバージョンエラーが出た場合の対処
$ bundle install
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, runbundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java
.
Fetching gem metadata from https://rubygems.org/.........
Your bundle is locked to mimemagic (0.3.5), but that version could not be found
in any of the sources listed in your Gemfile. If you haven't changed sources,
that means the author of mimemagic (0.3.5) has removed it. You'll need to update
your bundle to a version other than mimemagic (0.3.5) that hasn't been removed
in order to install.$ rake secret
Could not find rake-13.0.3 in any of the sources
Runbundle install
to install missing gems.bundle update mimemagic
- 投稿日:2021-03-25T11:31:50+09:00
RSpec 多対多関係 モデルテスト(例.Tagモデル)
はじめに
rspecのTagのmodelテストをする際、中間テーブル(post_tag)を介したやり方に苦戦したため、
factory_botを用いて、多対多関係 (has_many through) のテスト作成方法をご説明致します。テーブル
post
とtag
の間にpost_tag
テーブルがある状態です。到達点
以下の2点を達成する
・中間テーブルを介したmodelテストのFactoryBotを理解する
・中間テーブルを介したmodelテストの記述方法を理解する流れ
① 各モデルのvalidatesを確認
② FactoryBotの記述
③ modelテストの記述① 各モデルのvalidatesを確認
app/models/post.rbclass Post < ApplicationRecord has_many :post_tags, dependent: :destroy has_many :tags, through: :post_tags validates :title, presence: true, length: { maximum: 60 } validates :body, presence: true, length: { maximum: 2000 } endapp/models/post.rbclass Tag < ApplicationRecord has_many :post_tags, dependent: :destroy has_many :posts, through: :post_tags validates :name, presence: true, length: { maximum: 50 } endapp/models/post.rbclass PostTag < ApplicationRecord belongs_to :post belongs_to :tag validates :post_id, presence: true validates :tag_id, presence: true② FactoryBotの記述
app/spec/factories/post.rbFactoryBot.define do factory :post do sequence(:title) { |n| "title-#{n}" } sequence(:body) { |n| "body-#{n}" } after(:create) do |post| create_list(:post_tag, 1, post: post, tag: create(:tag)) end end end
after(:create)
を使用することで、post生成後に、tagとpost_tagが生成されます。
app/spec/factories/tag.rbFactoryBot.define do factory :tag do sequence(:name) { |n| "tag-#{n}" } end end
sequence
でユニークnameを生成できます。
app/spec/factories/post_tag.rbFactoryBot.define do factory :post_tag do association :post association :tag end end
association :post
association :tag
とすることで、
post_tagのmodelテストにおいて
let(:post_tag) { create(:post_tag) }
と記述するだけで
postとtagも生成できます。ただし、associationは
has_many
側(今回の場合,post,tag)では記述せず、
belong_to
側でのみ使用しましょう。
③ modelテストの記述
app/spec/requests/post.rbRSpec.describe Post, type: :model do let(:post) { create(:post) } it "タイトル、本文、user_idがある場合、有効であること" do expect(post).to be_valid end it "user_idがない場合、無効であること" do post.user_id = nil expect(post).to be_invalid end describe "タイトル" do it "タイトルがない場合、無効であること" do post.title = nil expect(post).to be_invalid expect(post.errors[:title]).to include("を入力してください") end context "タイトルが60文字以下の場合" do it "有効であること" do post.title = "1" * 60 expect(post).to be_valid end end context "タイトルが61文字以上の場合" do it "無効であること" do post.title = "1" * 61 expect(post).to be_invalid end end end describe "本文" do it "本文がない場合、無効であること" do post.body = nil expect(post).to be_invalid expect(post.errors[:body]).to include("を入力してください") end context "本文が2000文字以下の場合" do it "有効であること" do post.body = "1" * 2000 expect(post).to be_valid end end context "本文が2001文字以上の場合" do it "無効であること" do post.body = "1" * 2001 expect(post).to be_invalid end end end endapp/spec/requests/tag.rbRSpec.describe Tag, type: :model do let(:tag) { create(:tag) } describe "name" do it "タグ名がある場合、有効であること" do expect(tag).to be_valid end it "タグ名がない場合、無効であること" do tag.name = nil expect(tag).to be_invalid expect(tag.errors[:name]).to include("を入力してください") end context "タグ名が50文字以下の場合" do it "有効であること" do tag.name = "1" * 50 expect(tag).to be_valid end end context "タグ名が51文字以上の場合" do it "無効であること" do tag.name = "1" * 51 expect(tag).to be_invalid expect(tag.errors[:name]).to include("は50文字以内で入力してください") end end end endapp/spec/requests/post_tag.rbRSpec.describe PostTag, type: :model do let(:post_tag) { create(:post_tag) } it "post_idとtag_idがある場合、有効であること" do expect(post_tag).to be_valid end it "post_idがない場合、無効であること" do post_tag.post_id = nil expect(post_tag).to be_invalid end it "tag_idがない場合、無効であること" do post_tag.tag_id = nil expect(post_tag).to be_invalid end end
association
によってlet(:post_tag) { create(:post_tag) }
が一文で済みました。
なお、itやcontext内の文章は、英語だとスペルミス等が出る可能性があるため、基本日本語にしております。間違い等がありましたらご指摘の方よろしくお願いします。
参考記事
FactoryBot(FactoryGirl)チートシート
factory_girl で最低限知っておきたい4つの使い方
FactoryBot(旧FactoryGirl)で関連データを同時に生成する方法いろいろ
- 投稿日:2021-03-25T11:26:34+09:00
バリデーションの書き方(Rails)
バリデーションとは
バリデーションは、正しいデータだけをデータベースに保存するために制約をかける事です。
model
に書くことでデータベースに保存する前に受け取った情報を正しいのか判定させます。空でないこと
validates :name, presence: true空であること
validates :name, absence: true一意性であること(重複していないこと)
validates :name, uniqueness: true文字数制限
validates :name, length: { minimum: 2 } # 2文字以上 validates :name, length: { maximum: 50 } # 50文字以下 validates :name, length: { in: 2..50 } # 2文字以上50文字以下 validates :name, length: { is: 6 } # 6文字のみBoolian型
validates :publish, inclusion: { in: [true, false] }参考