20200319のRailsに関する記事は24件です。

capistranoでbundle exec cap production deployを実行した時のエラー

何が起こったか?

capistranoを設定して、bundle exec cap production deployを実行して自動デプロイを行おうとしたところ以下のようなエラーに遭遇した。

terminal
OpenSSH keys only supported if ED25519 is available (NotImplementedError)
net-ssh requires the following gems for ed25519 support:
 * ed25519 (>= 1.2, < 2.0)
 * bcrypt_pbkdf (>= 1.0, < 2.0)
See https://github.com/net-ssh/net-ssh/issues/565 for more information
Gem::LoadError : "ed25519 is not part of the bundle. Add it to your Gemfile."
(Backtrace restricted to imported tasks)
cap aborted!
NotImplementedError: OpenSSH keys only supported if ED25519 is available
net-ssh requires the following gems for ed25519 support:
 * ed25519 (>= 1.2, < 2.0)
 * bcrypt_pbkdf (>= 1.0, < 2.0)
See https://github.com/net-ssh/net-ssh/issues/565 for more information
Gem::LoadError : "ed25519 is not part of the bundle. Add it to your Gemfile."

Tasks: TOP => rbenv:validate
(See full trace by running task with --trace)

対処法

以下のgemを追加して、buinle installすると解決した。

Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 3.6'
  gem 'capistrano'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'

  + gem 'ed25519'
  + gem 'bcrypt_pbkdf'
end

以上

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

[HowTo]ActiveStorage/アバター画像を登録&表示

先日、Active Storageを使用してアバター登録機能を実装しましたので、備忘録として以下に手順などをまとめておきます!
皆様の開発に少しでも役立てていただければ幸いです。

Active Storageとは

Active Storageとは、Rails 5.2以降に追加された機能で、ファイルのアップロードを可能にします。
似たような機能でCarrierWaveというものもございますが、こちらは過去に記事にしていたので、
今回はActive Storageを使用することにしました。
https://qiita.com/Tatsu88/items/66374abda7245a006ea0

Active Storageの特徴

ActiveStorageはactive_storage_attachmentsとactive_storage_blobsの2つのテーブルを作成します。
アップロードした情報はこれらのテーブルに格納され、モデルと関連づける必要があります。

完成イメージ

今回はマイページのアバター実装を目指します。
まず、アバター情報がないときは以下のイメージとなります。

マイページ(アバターなし)

demo

登録画面

アバター情報は以下にて、登録します。
demo

上記にてアバター情報を登録するとマイページに表示できるようにします。
demo

下準備

ImageMagickとmini_magickのインストール

Active Storageで画像を加工してから(サイズや色など)アップロードするには別のツールをインストールする必要があります。
ImageMagickという画像変換ツールと、それをRailsから使うためのmini_magickというgemをインストールしましょう。

ImageMagickのインストール

ImageMagickは、コマンドラインから簡単に画像の保存形式の変更などが行えるツールです。
ターミナルで下記のコマンドを実行してください。

ターミナル
$ brew install imagemagick

mini_magickのインストール

続いて、mini_magickをインストールしましょう。
mini_magickは、Gemの一種なので、Gemfileに記載します。

Gemfile
gem 'mini_magick'
ターミナル
$ bundle install

#gemを追加したので、必要に応じてrails sは再接続しましょう

Active Storageのインストール

上記にて下準備ができましたので、早速Active Storageをインストールしましょう。

ターミナル
$ rails active_storage:install

#上記で作成したマイグレーションファイルをマイグレートしましょう。(編集は不要です)
$ rails db:migrate

上記コマンドにて、以下のテーブルが作成され、アップロードした情報はこちらに格納されます。
- active_storage_attachments
- active_storage_blobs

関連モデルの編集

上記にてActive Storageの準備ができましたので、続いて関連するモデルを編集しましょう。
今回は"User"モデルに対して、アップロードされた画像情報を"avatar"として紐付けます。

/models/user.rb
has_one_attached :avatar

view:登録画面

今回は、form_withを使用して情報を登録します。
先ほどモデルに記載した情報をベースに記載します。

view(抜粋)
= form_with model: @user, url: profile_update_user_path ,method: :patch, local:true do |f|
 .form-group
   = f.label :プロフィール写真
   = f.file_field :avatar
#既に画像設定されている場合は、その内容を削除します。
  -if @user.avatar.attached?
   =@user.avatar.purge
 .form-group
   %p.form-group__text--center
   = f.submit '変更する', class: "btn-default btn-red"

view:登録内容表示画面

上記記述にて登録した内容を表示するviewを作成します。
ポイントとしては、アバター画像がある場合とない場合で表示する画像を分けてます。
アバター画像の有無は".attached?"メソッドを使用してます。
nil?やblank?やpresent?を使うとうまくいかないので、ご注意ください。

view(抜粋)
.mypage_top_container
 .mypage_top_container_avator
  .mypage_top_container_avator_main
  -if @user.avatar.attached?
   =image_tag @user.avatar, class:"avatar"
  -else
   =image_tag ("noimage.png"),class:"avatar"

以上で設定したアバター画像を表示することができます!
その他、コントローラやルーティングなど準備は必要となりますが、各自設定によると思われますので、
今回は割愛させていただきます。

参照

Active Storage の概要
https://railsguides.jp/active_storage_overview.html

【Ruby入門】真偽判定present?の使い方をわかりやすく解説
https://www.sejuku.net/blog/66030

[Rails5.2]ActiveStorageの仕組み(図あり)と使ってみてわかったこと
https://qiita.com/eightfoursix/items/a47ce1bd945582f5d808

【Rails】image_tagの使い方を徹底解説!
https://pikawaka.com/rails/image_tag

ActiveStorage で画像を複数枚削除する方法
https://h-piiice16.hatenablog.com/entry/2018/09/24/141510

Active Strageを使用してユーザーのアバターを登録、表示する
https://re-engines.com/2018/03/12/active-strage%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E3%82%A2%E3%83%90%E3%82%BF%E3%83%BC%E3%82%92%E7%99%BB%E9%8C%B2%E3%80%81%E8%A1%A8%E7%A4%BA/

以上となります。最後までご覧いただき、ありがとうございました!
今後も学習した事項に関してQiitaに投稿していきますので、よろしくお願いします!
記述に何か誤りなどございましたら、お手数ですが、ご連絡いただけますと幸いです。

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

インクリメンタルサーチで追加済みユーザーが検索されないようにする

目的

チャットアプリのグループメンバー追加ページを以下の仕様で作成する。
- インクリメンタルサーチでメンバー検索をして登録リストに表示
- 登録リストに表示されたメンバーを登録ボタンで追加リストに登録
- 登録されたメンバーは登録リストに表示されない

問題点

登録されたメンバーが登録リストに表示されてしまう。

考え方

検索されたメンバーのIDが追加リストに登録されたメンバーのIDと重複しない場合のみ表示させれば良い。

コード

before.js
users.forEach(function (user) {
  if (user.id) {
    addUser(user);
  }
})
after.js
users.forEach(function (user) {
  let idNum = document.getElementById(user.id);
  if (user.id && !idNum) {
    addUser(user);
  }
})
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsで、どちらか一方のカラムを入力必須(二者択一)にするバリデーション

はじめに

Ruby on Rails で どちらか一方のカラムを入力必須にするバリデーションについて書きます。

具体的な例をあげると、ユーザーモデルのemailphone、どちらか片方だけに必ず値が入るようにバリデーションします。両方に値が入っている場合もNGです。

要件に合わなかったバリデーション

ググって下記のようなバリデーションを見つけましたが、両方入力した場合にバリデーションを通ってしまうので、要件には合いません。

app/models/user.rb
class User < ApplicationRecord
  # phoneが空ならば、emailを必須にする
  validates :email, presence: true, unless: :phone?

  # emailが空ならば、phoneを必須にする
  validates :phone, presence: true, unless: :email?
end
User.create!(name: "たなか", email: "test@example.com", phone: "08011112222")

=> #<User id: 1, name: "たなか", email: "tanaka@example.com", phone: "08011112222", created_at: "2020-03-19 12:29:20", updated_at: "2020-03-19 12:29:20">

要件にあったバリデーション

要件を満たすために、次のカスタムバリデーションを作成しました。

app/models/user.rb
class User < ApplicationRecord
  validate :required_either_email_or_phone

  private

  def required_either_email_or_phone
    # 演算子 ^ で排他的論理和(XOR)にしています
    # emailかphoneのどちらかの値があれば true
    # email、phoneどちらも入力されている場合や入力されていない場合は false
    return if email.present? ^ phone.present?

    errors.add(:base, 'メールアドレスまたは電話番号のどちらか一方を入力してください')
  end
end
User.create!(name: "たなか", email: "tanaka@example.com", phone: "08011112222")

# => ActiveRecord::RecordInvalid (バリデーションに失敗しました: emailまたはphoneのどちらか一方を入力してください)

User.create!(name: "たなか", email: nil, phone: nil)

# => ActiveRecord::RecordInvalid (バリデーションに失敗しました: emailまたはphoneのどちらか一方を入力してください)

User.create!(name: "たなか", email: "tanaka@example.com", phone: nil)

# => <User id: 2, name: "たなか", email: "tanaka@example.com", phone: nil, created_at: "2020-03-19 13:06:55", updated_at: "2020-03-19 13:06:55">

おわり

普段は論理和 || 演算子 か論理積 && 演算子 ばかりで、^ 演算子は使わないので、上記のコードを思いつくまでに時間をかけてしまいました…!

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

EC2サーバで生成した公開キーはどこからどこまでなのか

cat ~/.ssh/id_rsa.pub

コマンドで作った公開キーは、どこからどこまでなのか?

結論

ssh-rsa AAA...
から始まって、

...== ec2-user@ip-000-00-00-000
までが

公開キーです

GitHub で SSH keyを登録するときの参考になればと。

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

チーム開発 3/19

メモです
最終課題二日目
トップページを担当

検索機能をつける際に検索ボタンを画像に引っ付けたい
https://teratail.com/questions/60004
参考サイト
button_tagもしくはimage_submit_tagを使うと解決

画像の大きさを自由に変えた(ブロックに合わせた大きさ)
https://qiita.com/jag_507/items/79af40e12a2e50bbc04e
https://teratail.com/questions/39407
参考サイト
まず大きさを変えたい画像のimgにクラスをつける
そこに
max-width: 100%;
height: auto
を記述する

検索機能にクラスを書きたいがエラーが出た
多分form_tagの書き方が悪い
form_withで解決した

Formにcssの要素をつけたい
form{}で要素をつけれる

html li リストマーク(・)消す方法
list-style: none;

ブロック全体に画像を貼る時に使う
background-image: url(pict/bg-mainVisual-pict_pc.jpg)

まとめ(全体)
トップページ
部分テンプレート完成

デバイス
サーバーサイドの新規は完成
見た目も90%ほど完成

マイページ
ビューを作りました
サイドバーの中身をみんなで考えたいです

商品の出品ページ
見た目のみ

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

定義してないのになぜか使える activated? admin? メソッド Ruby on Rails チュートリアル

こんなメソッド定義してないぞ?と思いきや、
Railsでは真偽値をとるカラムであれば、モデル.カラム名?で真偽値を取得できるらしいです。

user_model_account_activation.png

>> user = User.first
  User Load (0.1ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2020-03-15 10:30:06", updated_at: "2020-03-15 10:30:06", password_digest: "$2a$10$XvC6suqKbRRIHIm8nQOyjeQcKJixPXdm1b331TQJ7y5...", remember_digest: nil, admin: true, activation_digest: "$2a$10$5/9pDzSQIJdzpaAbFCJZO.qptq0BYtnH.Q/sBwP5epB...", activated: true, activated_at: "2020-03-15 10:30:06">

user.admin?
=>true

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

初めてのbootstrap導入(rails)

はじめに

bootstrapを導入する時に手間取ってしまったので、初めてbootstrapを触ってみる人でもわかりやすく、導入手順を一からおさらいします:baby_tone1:超初級編です:baby_tone1:

① Gemfileの末尾にbootstrapを追加

Gemfile
gem 'bootstrap'

今回はバージョン指定はしません。
この時、compass-railsというgemが追加されてあるとエラーを吐いてしまうので、なくて問題ないようなら削除します。

② gemの更新

terminal
$ bundle install

③ application.cssにbootstrapを導入

app>assets>stylesheet>application.css

application.css
@import "bootstrap";

application.cssをapplication.scssに名前変更

④ application.jsにもbootstrapを適用

app>assets>javascripts>application.js

application.js
//= require bootstrap

⑤ bootstrapを挿入

bootstrapから、好きなデザインを探し、適応させたいビューファイルに挿入します。
bootstrapトップページから、ヘッダーのDocumentation->左にあるCommponentsから探します。

e.g.) 今回は、headerにNavbarを使います。
app>views>layouts>application.html.erb

bootstrap navbar.png

application.html.erb
<header>
  ここにコピーしたコードを貼り付け
</header>

これでサーバーを起動させて該当ページを表示させると、下のようにbootstrapが適用されます。

bootstrap navbar適用後.png

後はエディタのbootstrapをコピーした部分のリンクや表示させたい文字などを調節して完成です!やったね!

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

RailsのformにAjaxを実装する前提

RailsにjQueryを使ったAjaxを適用するために色々調べました。
個人的な備忘録として残します。

configを設定

config/application.rb
require File.expand_path('../boot', __FILE__)

module SampleApp
  class Application < Rails::Application
    config.action_view.embed_authenticity_token_in_remote_forms = true    # 追加
  end
end

コントローラーの変更

class HogesController < ApplicationController
  def hoge
    respond_to do |format|
      format.html redirect_to hoge_path 
      format.js    # ※下
    end
  end
end

※ renderで指定しなければアクション名.js.erbを探す

テンプレートの変更

form_withを使っている場合(推奨)

remoteはデフォルトでtrueのでやることなし
(falseにしたい場合はlocal: trueを追加)

app/view/hoges/hoge.html.erb
<div id="ajax-test">
  <%= form_with ... do |f| %>
    <%= f.submit "hogehoge" %>
  <% end %>
</div>

form_for, form_tagを使っている場合、

オプションにremote: trueを付ける。

app/view/hoges/hoge.html.erb
<div id="ajax-test">
  <%= form_for ..., remote: true do |f| %>
    <%= f.submit "hogehoge" %>
  <% end %>
</div>

コントローラーでrenderしなかった場合、以下の点に注意してファイル.js.erbを追加
・適用したいテンプレートと同じ場所に配置
・ファイル名はコントローラーのアクション名と同じ名前に設定

app/view/hoges/hoge.js.erb
$("#ajax-test").html("<%= 'さあ、遠慮なく私をhogeりなさい!' %>");

記述はjQueryで。

.html("...");の部分を

.html("<%= escape_javascript(render('hoges/hoge')) %>");
.html("<%= j ( render('hoges/hoge') ) %>");でも可
などとすると色々できる。

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

redis-railsのセッション有効期限の挙動を確かめて遊ぶ

redis-railsのセッション有効期限の挙動をチェック

ローカルでサイトにアクセスすることで3ヶ月の期限付きセッションデータが生成される設定をしている。

redisを起動

command
redis-cli

DB1を選択する(設定によって変わります)

redis-commands
select 1

サイトにアクセス、キー一覧を取得。
=>1件のデータが作られている

7889224とは秒数のことで、有効期限である。
77042128-7e4ff380-69fe-11ea-86d9-fb4b7b14e5e6.png

【有効期限を無期限にするとどうなる?】

再度サイトにアクセス

  • データは1件しかないので、セッションは新規に作られた訳ではない
  • 有効期限が無期限(-1)になり、過去のセッション情報が更新されたことがわかる

77042103-75f7b880-69fe-11ea-81d8-c4e4d54a47c0.png

【有効期限を60秒に変更してみた】

再度変更後サイトにアクセス

  • 先ほど、無期限に設定したセッションデータの有効期限が60秒に更新された
  • 徐々に秒数のカウントが減っていき、最後は-2(データ見つからない)になりました。

77042331-d850b900-69fe-11ea-9164-a820664fc4c5.png

複数のユーザーがいる場合の挙動はどうなる?

プライベートブラウザと通常のブラウザの2種類を用いて、2種類のセッションを作成した

77042611-54e39780-69ff-11ea-860a-e77a1fd9c037.png

1つ目も2つ目も、有効期限は60ヶ月に設定している
77042805-ad1a9980-69ff-11ea-84cc-791ff88a6eb8.png

【有効期限を60秒に変更し片方だけサイトにアクセスする】

サイトにアクセスしたセッションは有効期限が更新され、60秒後には消えることになった。
アクセスしていない方は残り続けている。

画像では残り49秒で消えると表示されている
77042887-ce7b8580-69ff-11ea-85df-4cd428e018ce.png

片方のセッションは60秒が経過し、削除されました

77042984-f9fe7000-69ff-11ea-857e-3ba23a2f6d10.png

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

Ruby on Rails チュートリアル学習記録 第6章

第4、5章については特に書く内容がなかったため学習記録は付けませんでした

6.1

特になし

6.2

特になし

6.3

heroku run rails db:migratebash: heroku: command not foundというエラーメッセージ。
3章の時と同じ方法で解決
nvm install node
npm install -g heroku-cli
を実行後、あらためてheroku run rails db:migrateを実行

6.4

特になし

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

【Rails】フレンドリーフォワード

フレンドリーファワード

ログインしていないユーザーが編集ボタンをクリックする際に、ログイン後にトップページではなく編集ページに飛ぶようにしたい。
そういった機能を追加できるのがフレンドリーフォワードです。

実装

sessions_helper.rb
  def store_location
    session[:forwarding_url] = request.original_url if request.get?             
  end
users_controller.rb
    def logged_in_user                                                                
      unless logged_in
        store_location                                 
        flash[:danger] = "please login"
        redirect_to login_url                                                   
      end
    end

ユーザーのログイン時にフレンドリーフォワードを実装するにはセッションヘルパーにstore_locationを定義し、users_controller.rbにてlogged_in_userメソッドを定義します。

まずlogged_in_userでユーザーがログインしていない場合にstore_locationを実行させ、現時点のURLをsession[:forwarding_url]に保存します。

original_urlはhttp(s)以外も扱えるよう指定しています。
request.get?でGETリクエストの時だけ値を格納しているように指定しているのは、ログインしていないユーザがフォームで送信した場合にurlを転送先に保存させないためです。

sessions_helper.rb
  def redirect_back_or(default)
    redirect_to(session[:forwarding_url] || default)
    session.delete(:forwarding_url)
  end

  def store_location
    session[:forwarding_url] = request.original_url if request.get?             
  end
sessions_controller.rb
  def create
    @user = User.find_by(email: params[:session][:email].downcase)
    if @user && @user.authenticate(params[:session][:password])true
      log_in @user
      params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
      redirect_back_or @user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

そしてセッションヘルパーにredirect_or_backメソッドを追加し、sessions_controller.rbcreateアクションにてredirect_back_or @userを追記します。

session[:forwarding_url] || defaultsession[:forwarding_url]の値がnillだった場合にdefaultになるようになっています。

session.delete(:forwarding_url)ではログイン後に指定のパスに移動した後に:forwarding_urlを削除するようにしています。
こうすることで次回ログインした時に保存していたURLに飛ぶことを防いでいます。

上記手順でフレンドリーフォワードを実装できました。

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

elasticbeanstalkにcronoを設定したので、そのconfig

Elasticbeanstalk + rails + crono

railsでcron的なものを使いたかったけど、crontabを触りたくなかったので、cronoを使うことにした.その設定ファイル(結構作るのに時間かかったので。。。)
Cronoはこちら
I would like to use something like cron with rails, but didn't want to use crontab, so I try to use crono(I know it may not be maintained, but...), here is the config which I used.

環境

# rails -v
Rails 6.0.2.1
# uname -a
Linux ip-172-31-27-188 4.14.165-103.209.amzn1.x86_64 #1 SMP Sun Feb 9 00:23:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

設定ファイル

# cat .ebextensions/05_crono.config 
commands:
  create_post_dir:
    command: "mkdir -p /opt/elasticbeanstalk/hooks/appdeploy/post"
    ignoreErrors: true

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/50_restart_crono.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      EB_APP_DEPLOY_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
      EB_APP_PID_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
      EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
      EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
      EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)

      . $EB_SUPPORT_DIR/envvars
      . $EB_SCRIPT_DIR/use-app-ruby.sh
      PID=$EB_APP_PID_DIR/crono.pid
      cd $EB_APP_DEPLOY_DIR
      if [ -f $PID ] 
      then
        su -s /bin/bash -c "kill -TERM `cat $PID`" $EB_APP_USER
        su -s /bin/bash -c "rm -rf $PID" $EB_APP_USER
      fi
      . $EB_SUPPORT_DIR/envvars.d/sysenv
      sleep 10
      su -s /bin/bash -c "bundle exec crono start -P $PID " $EB_APP_USER
    "/opt/elasticbeanstalk/hooks/appdeploy/pre/03_mute_crono.sh":
      mode: "000755"
      owner: root
      group: root
      content: |
        #!/usr/bin/env bash
        EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
        EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
        EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
        . $EB_SUPPORT_DIR/envvars
        . $EB_SCRIPT_DIR/use-app-ruby.sh
        PID=$EB_APP_PID_DIR/crono.pid
        if [ -f $PID ] 
        then
          su -s /bin/bash -c "kill -USR1 `cat $PID`" $EB_APP_USER
        fi

テストに使ったjob

class CronoTestJob < ApplicationJob
  queue_as :default

  def logger
    Crono.logger.nil? ? Rails.logger : Crono.logger
  end

  def perform(*args)
    logger.info '*** start crono test job ***'
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsのGravatarで表示するデフォルト画像を変更する

いきさつ

Railsのチュートリアルを進めていた時に、Gravatarを用いてユーザのプロフィール画像を設定していました。その際、
「デフォルト画像をもう少しオシャレにできないものか」
と思ったので、Gravatarのデフォルト画像変更方法について調べました。
ちなみにデフォルト画像は以下の通りです。
00000000000000000000000000000000.jpg

Gravatarとは

画像をアップロードし、指定したメールアドレスと画像を関連づけることができる無料のサービスです。
チュートリアルでは、ユーザの画像を指定をするコードは以下の通りになっていると思います。

users_helper.rb
def gravatar_for(user, options = { size: 80 })
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    size = options[:size]
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
    image_tag(gravatar_url, alt: user.name, class: "gravatar")
end

それぞれのユーザの画像は、表示する画像のURLを指定するgravatar_urlに依存します。

gravatar_urlのパラメータ

今の段階では、表示する画像のURLとして
https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}
が指定されています。
このパスの指定に何かヒントがありそうです。公式サイトにあったこちらの記事によると、

If you'd prefer to use your own default image (perhaps your logo, a funny face, whatever), then you can easily do so by supplying the URL to an image in the d= or default= parameter. The URL should be URL-encoded to ensure that it carries across correctly, for example:<img src="https://www.gravatar.com/avatar/00000000000000000000000000000000?d=https%3A%2F%2Fexample.com%2Fimages%2Favatar.jpg" />

とのこと。つまり、URLのdまたはdefaultというパラメータに設定したいパスを指定することで、任意の画像をデフォルト画像に指定できるとのこと。
ただし、以下の制約があります。

MUST be publicly available (e.g. cannot be on an intranet, on a local development machine, behind HTTP Auth or some other firewall etc). Default images are passed through a security scan to avoid malicious content.
MUST be accessible via HTTP or HTTPS on the standard ports, 80 and 443, respectively.
MUST have a recognizable image extension (jpg, jpeg, gif, png)
MUST NOT include a querystring (if it does, it will be ignored)

  • 誰もがアクセス可能な画像であること(公開範囲を限定している画像やローカル環境にある画像はNG)。
  • HTTP, HTTPSのポート番号がそれぞれ80番、443番であること。
  • 拡張子がjpg, jpeg, gif, pngのいずれかであること。
  • パスにURLパラメータを用いないこと。 だそうです。

実際にやってみる

現段階では、ユーザの一覧画面は以下の通りです。
スクリーンショット 2020-03-19 12.24.46.png
デフォルト画像として、先ほどお見せした水色の画像が設定されています。
こちらの記事によると、例えばdのパラメータにrobohashを指定すると、以下のようなロボットの画像がデフォルト画像になるようです。
00000000000000000000000000000000.png
実際にuser_helpers.rbを以下のように変更します。gravatar_urlのdにrobohashを設定しました。

users_helper.rb
def gravatar_for(user, options = { size: 80 })
    gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
    size = options[:size]
    gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?d=robohash&?s=#{size}"
    image_tag(gravatar_url, alt: user.name, class: "gravatar")
end

すると
スクリーンショット 2020-03-19 12.27.07.png
確かにデフォルオ画像がロボットになりましたね。
別の画像も試してみます。参考文献の記載にしたがって、次はdにretroを指定します。

gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?d=retro&?s=#{size}"

スクリーンショット 2020-03-19 12.32.09.png
デフォルト画像がドット絵になりました。
最後に、こちらの画像を試してみます(特に悪意はありません)。
otaku_winter (1).png
dに画像のURLを指定します。

gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?d=https://resizer6.myct.jp/img/79313116268/otaku_winter.png&?s=#{size}"

スクリーンショット 2020-03-19 12.38.00.png
こちらもできました。

まとめ

Gravatarのデフォルト画像は、dというパラメータに画像のパスを指定することで変更することができます。

参考文献

https://ja.gravatar.com/site/implement/images/

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

Rails5 slim 掲示板やトピック等でのtextの表示形式

掲示板を実装した時に改行やスペース、URLの反映がちょっと手間取ったのでメモ

ユーザーがフォームで入力したtextを取得して掲示板に表示させる時何も設定していないと改行等全く反映されない。
コピペしたURLも文字列として扱われてリンク表示にならないです。あとスペースも反映されない。

-require 'uri'
- @board.comments.each do |comment|
| >
= simple_format(text_url_to_link(h(comment.content.gsub(/ /, '&nbsp;').html_safe)), {}, sanitize: false)

上記の記載で私の場合は解決できました。

require 'uri

simple_format(text_url_to_link(h(comment.content.gsub(/ /, '&nbsp;').html_safe)), {}, sanitize: false)

がキモ。それぞれの意味についてはググれば出てきます。
この記載で「改行、半角スペース、全角スペース、URLリンク」が全て反映されるようになりました。

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

Rails5 slim bootstrap4 placeholderの反映

Rais5でBootstrap4を使用した際にplaceholderが反映されなかった時のメモ

slim使用しているとbootstrapの記載で迷うことが多くて、、

今回はplaceholderを反映させる記載方法メモ

=f.text_field :term, class: 'form-control', :placeholder => '※月※日〜※月※日、平日※時〜※時の間'

私はこの記載で反映されました。
バージョンによって違ったり、slimでの記載方法もあるのでちょっとたどり着くのに時間がかかりました。。

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

【Rails/Ruby】クラスメソッドとインスタンスメソッドの使い分け

「クラスメソッドとインスタンスメソッドの使い分けについて教えてください」
って前に聞かれてちょっと困ったことを思い出したのでまとめてみました~???

※クラス・インスタンスの概念の説明やクラスメソッド・インスタンスメソッドの詳しい説明は端折ってます~!

クラスメソッド

・クラスに対して使う
 例:newメソッド/など

# インスタンスの生成
Animals.new

・DBからデータを取得したり保存するときに使う
 例:allメソッド/findメソッド/createメソッドなど

# 引数に一致するデータをDBから取得する
User.find(1)

・外部ファイルやサイトからデータを取得する(データを取得し、インスタンスを作成する)ときに使う
 例:スクレイピングなど

・全体で扱うべき情報を扱うときに使う
 例:投稿の総数など

インスタンスメソッド

・生成した個々のインスタンス(投稿1つ1つ、ユーザー1人1人など)に対して使う
 例:update/destroy/eachなど

# userにインスタンスを代入
user = User.find(1)
# userに代入したデータを削除する
user.destroy

最後に

個人的にわかりやすいと思ったクラスとインスタンスの説明で終わります~!

クラス = 野菜という大枠

インスタンス = ニンジン・オクラ・ブロッコリーなど細かな種類

クラスとインスタンスの概念って理解するのってやっぱり難しいですね?

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

チーム開発 3/18

メモで
最終課題1日目
ER図法
テーブル、カラム、タイプ、オプション
ターミナル
Bundle install
Rails s

問題:Git hubでmasterに記入するが共有されない
解決? :Masterに記述する場合は親に当たる人(masterを作った人)が書かないと共有されないかも?
セッティングで招待?しないと共有されない

問題:親じゃない人がプルリクエストした場合にその人がマスターのブランチに戻した時に
記述したところが消えてしまう

前のところのまま更新されていない?
変なエラー?プルリクエストとした後にセッティングした時におかしくなった?
一回招待を取り消してみて再招待してみる
ファイルが消えてしまったためもう一度git cloneしていく
やり直し
解決:やり直し

☑️環境設定

ER図法を提出
問題点、修正点を探す
宅配のアドレスにカラムは1つで十分
サイズのテーブルを消してユーザーに書いてもらう形にする、ユーザーのテーブルにカラムとして追加

まとめ 次どうするか
トップページを二人でやる
トップページは金曜日
ユーザーのログインページ1人だと厳しいかも
新規登録が大変
テストもある

誰が何をするかを決める

__________________________________________________________
調べた事
●Desktopのブランチ消す時は上のバー(アップルのマークある方)にブランチとあるのでそこのデリートで消せる
●has_one
従属する側のモデルに belongs_to を記述し、
従属させる側のモデルに has_one を記述する。
1体1の関係の時使うかも?
かってにidを取って来てくれる
belongs_toも一緒

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

bootstrap3から4への移行方法について (Rails5)

今回はbootstrapのバージョン変更について書いていきたいと思います。

経緯はこうです。ポートフォリオ製作の中、週一の専用メンタリングがあり時間もわずかのところでメンターの方から

 

『あれ?bootstrapは3を使ってるんですね!』

 

な、なんだ!? 教材を参考にして制作を進めてるからそもそもバージョンにこだわりがなくてbootstrap3になっていたわけだが何かまずいのかな?と聞いてみると

 

『今はbootstrap4が主流ですね。特にこだわりがなければ新しいのを使った方がいいですよー。あとは今であれば困ったときにbootstrap4の方が似たようなケースも多いと思うので解決しやすいですよ!!』

なるほど。そしたらどうせ今後も使う機会もあると思うので新しいbootstrap4にバージョンを変更しよう!!

と意気込み、以下の記事を参考にしながらやってみました。

https://qiita.com/NaokiIshimura/items/c8db09daefff5c11dadf

なんだー簡単じゃんと思い いざアプリを立ち上げると

 

 

全然導入できねえ

 

こんなにバージョン更新が難しいとは。。。

やったこと

gemfile中に以下を記述しbundle install

gem 'bootstrap', '~> 4.1.1'
gem 'jquery-rails'  

sprockets-railsがv2.3.2.以上である必要があるらしいので以下コードでバージョン確認

$ bundle show |fgrep sprockets-rails
  * sprockets-rails (3.2.1) 問題なし

app/assets/stylesheets/application.scssの中に@import "bootstrap";があることを確認。またファイル名がcssのままだとよくないのでscssに変えておく
ここも今までのbootstrap3導入まででやっていたことなので問題なし。

 

ブートストラップJavaScriptはjQueryに依存しています。Rails 5.1以降を使用している場合は、jquery-railsgemをGemfileに追加します。

gem ' jquery-rails ' ここもbootstrap3導入まででやっていたことなので問題なし。

application.jsに以下を記述する。

//= require jquery3
//= require popper
//= require bootstrap-sprockets

rails s を再度して立ち上げる

エラー発生

ブートストラップエラー.png

内容をググりながらみていくと
Sass::SyntaxError in Pages#index
シンタックスエラーなのでコンパイルがうまくいってないのかな?

念のため他のページで読み込んでみるも特にエラー内容は変わらず

File to import not found or unreadable: bootstrap-sprockets.
この一行で検索をかけると

http://geekday.hatenablog.com/entry/2017/03/31/021052

同じような境遇の方がいたので早速みてみるも解決せず
タイポもなさそうだしバンドルインストール後railsサーバー再起動するも変わらずエラー

https://github.com/twbs/bootstrap-rubygem

bootstrap4の公式手順を見るも特にやってないことはないんだけどなあと途方に暮れました。まじで

 

 ここから解決方法!!!

というわけでメンターの方に助けを求めると

まずGemファイル内のgem 'bootstrap-sass'を削除した方がいいと
これはbootstrap3を導入するときの記述なので本質的なエラーとは関係ないかもしれないが余計な影響があるかもしれない

 

このエラー画像の下の赤いラインなんですが

@import "bootstrap-sprockets";

app/assets/stylesheets/application.scssの中にbootstrap3の名残で書いていたのですが、これがそもそもbootstrap4では必要がないらしいです なのでこれを削除

@import "bootstrap-sprockets"; File to import not found or unreadable: bootstrap-sprockets.とエラーメッセージが出ているのでこちらのファイルがないのに読み込みにいってます。 なので余談ですがapp/assets/stylesheets/application.scssの中に適当なファイル名を追記すると同じエラーが出ました。(@import "aaaaa";実際にこんなファイルはないので読み込めないですと表示されます) 

再度railsサーバー再起動すると無事に表示!!
3から4に変えたことでデザインは崩れていましたが。

そもそも

 いやーここまで長かった。スタックオーバーフロウの英語の記事もGoogle先生に翻訳してもらいながら他の関係ありそうな記事を何件も読み半日以上格闘してました。
今回も残念ながら一人での解決はできませんでしたが惜しいところまで来ていたかと思います。

 

今後のエラー解決方法としては

バージョンを変える場合は以前のバージョンと更新したいバージョンの公式説明を読んでみる
これに関しては4の導入説明は読んでいたけど3の導入説明は探していなかったので3の記事を読んでいたら導入方法の違いがわかってもしかしたら解決できたかもしれません。更新手順を進める前にgitにpushしてからいろいろ変更しても大丈夫なようにすれば気軽に怪しい場所を削除して解決できるかなと思いました。

 

ニッチではありますが同じ境遇で同じエラーで困っている方は是非参考にしてください。

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

【Rails】 SCSS で Bootstrapライクな opacity-n(透過) を追加する

何をするの??

CSSでオブジェクトを透過したいときに、
opacity-85みたいな Bootstrapライクに指定したかったので
SCSSを使って追加しちゃいます

SCSS の記述?

SCSSファイルに以下の記述を追加するだけで、
opacity-0 = 0% (透過) から opacity-100 = 100% (非透過) まで全ての透過度を可変で CSSセレクタ としてつかうことができます

opacity.scss
@for $i from 0 through 100 {
  .opacity-#{$i} {opacity: $i * 0.01;}
}
some.erb.html
<div class="opacity-62">
  # 62%の透過になる
</div>

ファイルとして実装する方法(おまけ)

アセットパイプラインで実装する場合 ?

application.scssopacity.scss
の順にロードされるように配置する

/app/assets/stylesheets/application.scss
 *= require_tree .
 // もしくは 
 *= require_tree opacity
/app/assets/stylesheets/opacity.scss
@for $i from 0 through 100 {
  .opacity-#{$i} {opacity: $i * 0.01;}
}

webpacker で実装する場合 ?

application.jsapplication.scssopacity.scss
の順にロードされるように配置する
追加位置はいずれも後ろの方でOK

/app/javascript/packs/application.js
import "../stylesheets/application";
/app/javascript/stylesheets/application.scss
@import "opacity";
/app/javascript/stylesheets/opacity.scss
@for $i from 0 through 100 {
  .opacity-#{$i} {opacity: $i * 0.01;}
}

CSS も量が多くなったら別ファイルに分けると、見通しが良いですね?

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

ec2をターミナルで操作するときに詰まった話(fatal: Could not read from remote repository.)

(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
を参考に、AWSにrailsアプリをあげようとしていたときの凡ミスについて。

エラー箇所について

上記の記事で

[~]$ ssh mumu_key_rsa

でログインした後に、

[ユーザー名|~]$ vim .gitconfig

で、諸々の設定を記述するところがある。

そこで、記事通り、下記のように設定すればよかった。

[user]
  name = your_name (#gitに登録した自分の名前)
  email = hoge@hoge.com (#git登録時の自分のメアド)

[alias] (#これはお好きに)
  a = add
  b = branch
  ch = checkout
  st = status

[color] (#色付け)
  ui = true

# githubの場合
[url "github:"] (#pull、pushのための設定)
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:

しかしながら、筆者は

[user]
  name = your_name (#gitに登録した自分の名前)
  email = hoge@hoge.com (#git登録時の自分のメアド)

[alias] (#これはお好きに)
  a = add
  b = branch
  ch = checkout
  st = status

[color] (#色付け)
  ui = true

# githubの場合
[url "github:"] (#pull、pushのための設定)
    InsteadOf = https://github.com/(ここに実際にcloneしたいアプリのレポジトリURLを書いていた)
    InsteadOf = git@github.com:(ここに実際にcloneしたいアプリのレポジトリURLを書いていた)

上記を見ていただければ分かる通り、無駄にレポジトリURLを記載してしまっていた。
その結果、git cloneで

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

と、言われてしまったのだった。

まとめ

(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで

この記事では、丁寧にコメントでここには○○を記述などと書いてくれている。

それをちゃんと読んでいなかった筆者は簡単な設定ミスで結構苦労した(3時間も使ってしまった)。

みなさんが、そして未来の自分が再びこんな凡ミスを犯さないためにも、備忘録的に書かせていただきました。

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

マイグレーション操作

はじめに

「Ruby on Rails 5 速習実践ガイド」の本の内容(Chapter4-1)に沿ってまとめと、他に調べて知ったことも書いてみようと思います。
(内容薄いですが、、、、)

Ruby on Rails 5 速習実践ガイド(Chapter4-1)

?マイグレーションの適用

2つのステップ

マイグレーションは基本的に2つのステップで行います。
1. Rubyのコードで、データベースのスキーマを変更するファイル、 「マイグレーション」ファイル を作成する
2. rails db:migrate コマンドで、作成した「マイグレーション」ファイルをデータベースに適用する

1つのマイグレーションは1つのバージョン

1つのマイグレーション(ファイル)が、 1つのバージョンとして、扱われます。
マイグレーションファイルを作成しただけでは、データベースは変更されず(バージョンは上がらず)、マイグレーションファイルを適用するとデータベースが変更されます。
マイグレーションを取り消す(バージョンを下げる)にも、マイグレーションファイルを削除するだけでは変更されないため、取り消すコマンドを実行して、操作を適用します。

?バージョンの上げ下げ

下のマイグレーションファイルは、Userテーブル作成し、nameカラムとemailカラムを持つことを記述されています。
changeメソッドの中に、「Userテーブルを作成する」というコードが書かれていれば、
マイグレーションの適用を取り消す際には、「Userテーブルを削除する」というコードが書かれているかのように処理をしてくれます。

db/migrate/[timestamp]_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

こちらのマイグレーションファイルは、nameカラムに入る文字列の長さを制限しています。
upメソッド にバージョンを上げる処理、 downメソッド にバージョンを下げる処理を記述しています。

db/migrate/[timestamp]_change_users_name_limit10.rb
class ChangeUsersNameLimit10 < ActiveRecord::Migration[6.0]
  def up
    change_column :Users, :name, :string, limit: 30
  end

  def down
    change_column :Users, :name, :string
  end
end

?schema.rbについて

Railsは、データベースの構造(スキーマ)を db/schema.rb というファイルに自動で出力します。
テーブル、カラムの構造を確認できます。

Railsガイドには、このように書かれています。

Railsのマイグレーションは強力ではありますが、データベースのスキーマを作成するための信頼できる情報源ではありません。
信頼できる情報源は、やはりデータベースです。Railsは、デフォルトでデータベーススキーマの最新の状態のキャプチャを試みるdb/schema.rbを生成します。

?主なコマンド

migrationまわり

migrationに関する主なコマンドまとめです

コマンド           意味
bin/rails db:migrate 最新までマイグレーションを適用する
bin/rails db:migrate VERSION=20200319 特定のバージョンまでマイグレーションが適用されていた状態にする
bin/rails db:rollback バージョンを1つ戻す
bin/rails db:rollback STEP=2 バージョンを指定したステップ数だけ戻す
bin/rails db:migrate:redo バージョンを1つ戻してから1つ上げる
bin/rails db:version     現在の適応されているバージョンを表示する

dbコマンド

主なdbコマンドも少しまとめてみました

コマンド 意味
bin/rails db:create データベースが作成される
bin/rails db:drop データベースの削除される
bin/rails db:reset db:dropし、db/schema.rbにもとづいてデータベースを作り直す

おしまい

↓こちら参考にしました?
Ruby on Rails 5 速習実践ガイド
Railsガイド
rake or rails コマンドでdbを扱うときのメモ

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

Ruby on Rails 削除関連まとめ

1. はじめに

アプリの作り始めに、「なんか気に入らないから1回削除して一から作り直したい」と思ったことはありませんか?
私はあります。そんな時に必要になる操作をまとめました。
すでにアプリを作りこんでいる場合は、削除して作り直すわけにもいきませんから変更の方法を探してみてください。

自分の環境

  • ruby 2.6.5
  • Rails 6.0.2
  • macOS Catalina 10.15.3

2. アプリの削除

アプリの削除をするにはアプリのフォルダを削除すればいいのですが、その前にデータベースを削除しておきましょう。
同じ名前でアプリを作り直したりしたときに以前のデータベースを利用してしまい、不具合が起きる可能性があります。
アプリケーションフォルダ内で、

$ rails db:drop

これでデータベースが削除されます。
そのあとは、以下コマンドでアプリフォルダを削除してもいいですし、ゴミ箱へと放り込んでもいいでしょう。

$ cd .. (1つ上のフォルダへ)
$ rm -rf [アプリ名]

ちなみに上記コマンドの意味は、

  • rm = 削除するというコマンド
  • -rf = ファイルでなくフォルダを削除するよという -r と「」というメッセージ表示はいらないよという -f の 組み合わせ
  • . = 現在のフォルダ

3. コントローラの削除

アプリケーションフォルダ内で以下のコマンドを実行します。
作成の際のrails generaterails gと省略できますが、destroyは出来ません。
ルーティングは自分でconfig/routes.rbをいじって消しましょう。

$ rails destroy controller [削除したいコントローラ名]

4. モデルの削除

マイグレーションを実行する前か後かで操作が変わるので注意。マイグレーション実行というのは、言い換えればデータベースにテーブルを作ること、もしくはrails db:migrateを実行することです。わからなかったら実行後の操作をしてみてください。

マイグレーション実行前

アプリケーションフォルダ内で以下のコマンドを実行します。
作成の際のrails generaterails gと省略できますが、destroyは出来ません。

$ rails destroy model [削除したいモデル名]

マイグレーション実行後

まずはマイグレーションまでしてみましょう。以下コマンドを実行。
説明の都合上、2つのモデルを作ってマイグレーションします。(なんの情報も持っていないモデルだけど気にしない。本当はカラム名:データ型を後ろにつけます)

$ rails g model user ← モデル作成
$ rails db:create ← データベース作成(まだデータベースを作っていない場合)
$ rails db:migrate ← テーブル作成

$ rails g model post
$ rails db:migrate (ここでやるから先の rails db:migrate はやらなくてもいい)

モデルを削除する際には、データベースにテーブルが作成されてしまっているのでそちらを削除してからモデルを削除する必要があります。

まずは以下コマンドを実行してみましょう。

$ rails db:migrate:status

マイグレーションを実行した一覧が出てきます。これが

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200318134652  Create users
   up     20200318134702  Create posts

Statusがupになっているということはこのマイグレーションが実行されている(テーブルが
作られている)ということ。

以下コマンドのどれかを実行して、削除したいモデルのマイグレーションを取り消しましょう。

$ rails db:rollback (1つだけ前の状態に戻す)
$ rails db:rollback STEP=2 (2つ前の状態に戻す)
$ rails db rollback VERSION=20200318134652
  (Migration ID:20200318134652のマイグレーションまで実行された状態に戻す)

マイグレーションが2つくらいならrails db:rollbackを2回やればいいですが、たくさん戻したいならステップ数やバージョンを指定すると楽ですね。(不整合が起きるため、過去の特定のマイグレーションだけを取り消すことはできません。)

これで実行したマイグレーションが取り消されたので、あとはマイグレーション実行前と同様にrails destroy [モデル名]で削除しましょう。

マイグレーション取り消しの前にモデルを削除してしまった場合

せっかちで先にrails destroy [モデル名]を実行してしまった人のため。
例えば先の例でpostモデルを削除してしまったとします。するとpostのマイグレーションファイルも削除されてしまいrails db:rollbackでマイグレーションを取り消すことすらできなくなります。(絶望)

その場合は、まず以下コマンドで新しくマイグレーションファイルを作成します。

$ rails g migration [マイグレーション名]

マイグレーション名はなんでもいいですが、わかりやすくdrop_postとでもしておきましょう。

するとdb/migrate/内に以下ファイルが作成されます。

20200318143822_drop_post.rb
class DropPost < ActiveRecord::Migration[6.0]
  def change
  end
end

changeメソッド内に以下の様に追記しましょう。

20200318143822_drop_post.rb
class DropPost < ActiveRecord::Migration[6.0]
  def change
    drop_table :post
  end
end

そしてマイグレーションを実行します。するとpostテーブルが削除されているため一件落着。

$ rails db:migrate

無駄なマイグレーションファイルが残ってしまうのが自分的に嫌です。ファイルを削除しても問題ないけどrails db:migrate:statusで表示される履歴の中にはしっかり残っています。(※マイグレーションファイルは削除しない様にしましょう)

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200318145751  Create users
   up     20200318150431  ********** NO FILE **********
   up     20200318150544  ********** NO FILE **********

5. scaffoldで作成したモデルやコントローラ等の削除

rails g scaffold [モデル名] カラム名:データ型 (カラム名:データ型...)でモデルやコントローラやルーティングなどを一括作成してくれます。詳しくは別記事を参照してください。

rails g scaffoldで作成したんだからもちろん削除は以下コマンド。全部スッキリ削除してくれます。

rails destroy scaffold [モデル名]

6. データベース内のデータを削除

モデルやコントローラ、ビューなどを作成し、色々試していているとデータベース内のデータがごちゃってきて初期状態に
戻したい時があると思います。そういうときは以下コマンドを実施。

rails db:reset

今あるデータベースを削除して新しくもう一度作ってくれます。db/seeds.rbを使って初期データ投入を行っている場合は初期データ投入も同時にやってくれるので、自分でrails db:seedを行うと二重にデータが入ってしまいます。

7. さいごに

他にも削除系の操作があれば教えてください。追記させていただきます。

@ruemura3

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

コメント機能の非同期通信

Gemfileの記述

Gemfileにjquery-railsが記載されているか確認し、記載されていない場合は最下部に記載してください。

〜省略〜
# Use jquery as the JavaScript library
gem 'jquery-rails'
〜省略〜

記述したときはターミナルで

bundle install

application.jsの記述を確認

application.jsに
//= require jquery
//= require rails-ujs
の記載がされているか確認します。なければ以下のように記述してください。

application.js
〜省略〜
//= require jquery
//= require rails-ujs 
//= require_tree .

必要なクラス名とID

ajaxの非同期通信を実装するために、事前にコメントのフォームにクラス名を与えておきます。
仮に
new_commentというid
textboxというclass
form__submitというclassをつけるとします。
【例】モデル名をTweetとします。

app/views/tweets/show.html.erb
<%= form_with(model: [@tweet, @comment], local: true, id: "new_comment") do |form| %> 
  <%= form.text_area :text, placeholder: "コメントする" , rows: "2", class: "textbox" %>
  <%= form.submit "送信", class: "form__submit" %>
<% end %>

コメント機能を非同期通信化

1.jQueryを記述するためのファイルを作成する
2.フォームが送信されたら、イベントが発火するようにする
3.非同期通信でコメントが保存されるようにする
4.respond_toを使用してHTMLとJSONの場合で処理を分ける
5.jbuilderを使用して、作成したメッセージをJSON形式で返す
6.返ってきたJSONをdoneメソッドで受取り、HTMLを作成する
7.エラー時の処理を行う
を作業していきます。

jQueryを記述するためのファイルを作成

JavaScriptファイルをassets/javascripts以下に作成します。今回はコメント機能の作成なのでcomment.jsのファイルを作ります。

フォームが送信されたら、イベントが発火

submitボタンを押した時に、イベントが発火するようにします。
comment.jsに、コメントフォームが送信された時フォームに入力された値を受け取れるようにします。
【例】

comment.js
$(function(){
  $('#new_comment').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);
  })
})

フォームが送信された時、というイベントを設定したい場合は、form要素を取得してonメソッドを使います。
今回のアプリの画面ではform要素のid属性が#new_commentにしています。フォームの送信についてonメソッドでイベントをセッティングする際は、form要素自体に設定するようにします。
最初から設定されているフォームの動作はキャンセルします。
フォームが送信される時、何も設定していない状態(デフォルトの状態)だとフォームを送信するための通信が行われるため、preventDefault()を使用してデフォルトのイベントを止めます。

FormData

フォームのデータの送信に使用することができます。その他にも、キーのついたデータを伝送するためにフォームとは独立して使用することもできます。今回はコメントフォームがあるので、そのフォームの情報を取得するのに使います。
new FormData(フォーム要素)とすることでFormDataを作成できます。
今回FormDataオブジェクトの引数はthisとなっていますが、イベントで設定したfunction内でthisを利用した場合は、イベントが発生したノード要素を指します。今回の場合は、new_commentというIDがついたフォームの情報を取得しています。

フォームの値を確認

comment.js
$(function(){
  $('#new_comment').on('submit', function(e){
    e.preventDefault();
    console.log(this)   #追加部分
    var formData = new FormData(this);
  })
})

検証の画面でコンソールを開き、thisの中身がフォームに入力した値が出力されていればOKです。
JavaScriptではconsole.logを用いてデバッグを行います。

非同期通信でコメントを保存

フォームに入力されたデータを取得したら、必要なAjax関数のオプションを揃えて非同期通信を行います。
1.フォームの送信が行われた時に、Ajaxによる非同期通信でcreateアクションを動かす
2.createアクション内でコメントを保存し、respond_toを使用してHTMLとJSONの場合で処理を分ける
console.log(this)は削除します。

comment.js
$(function(){
  $('#new_comment').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);   #追加〜
    var url = $(this).attr('action')
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: 'json',
      processData: false,
      contentType: false   #〜追加
    })
  })
})

フォームの送信先のurlを定義しています。$(this)は、thisで取得できる要素をjQueryオブジェクト化しています。

attrメソッド

要素が持つ指定属性の値を返します。
要素が指定属性を持っていない場合、関数はundefinedを返します。
今回はイベントが発生した要素のaction属性の値を取得しており、今回のaction属性にはフォームの送信先のurlの値が入っています。
これでリクエストを送信する先のURLを定義することができました。

processDataオプション

デフォルトではtrueになっており、dataに指定したオブジェクトをクエリ文字列(例: msg.txt?b1=%E3%81%8B&b2=%E3%81%8D )に変換する役割があります。
クエリ文字列とは、WebブラウザなどがWebサーバに送信するデータをURLの末尾に特定の形式で表記したものです。

contentTypeオプション

サーバにデータのファイル形式を伝えるヘッダです。こちらはデフォルトでは「text/xml」でコンテンツタイプをXMLとして返してきます。
ajaxのリクエストがFormDataのときはどちらの値も適切な状態で送ることが可能なため、falseにすることで設定が上書きされることを防ぎます。FormDataをつかってフォームの情報を取得した時には必ずfalseにするという認識です。
他にもAjaxリクエストを送信するオプションの参考です。
(http://js.studio-kingdom.com/jquery/ajax/ajax)

コメントを保存し、respond_toを使用してHTMLとJSONの場合で処理を分ける

非同期通信によって、comment#createを動かすことに成功し、正しくAjaxからdataを送れていれば、そのまま保存することが可能です。
保存ができていることを確認したら、respond_toを使用してHTMLとJSONの場合で処理を書いていきます。
【例】上のcomments_controller.rbが同期通信です。それを非同期通信の記述に編集します。

comments_controller.rb
class CommentsController < ApplicationController
def create
  Comment.create(comment_params)
end

private
def comment_params
  params.require(:comment).permit(:text).merge(user_id: current_user.id, tweet_id: params[:tweet_id])
  end
end
comments_controller.rb
def create
    @comment = Comment.create(comment_params)   #編集〜
    respond_to do |format|
      format.html { redirect_to tweet_path(params[:tweet_id])  }
      format.json
    end   #〜編集
  end

  private
 def comment_params
    params.require(:comment).permit(:text).merge(user_id: current_user.id, tweet_id: params[:tweet_id])
 end

ローカル変数commentは、スコープの関係でこの後のjbuilder側で使用できないので、インスタンス変数@commentに編集します。
respond_to doを使用し、リクエストされたformatによって処理を分けます。フォーマットがjsonの時は、format.jsonに引数としてインスタンスを渡します。今回はjbuilderを使ってJavaScriptに返すデータを作成します。

jbuilder

rails newコマンドでアプリケーションを作成した際にgemfileにデフォルトで記述されているgemで、入力データをJSON形式で出力するテンプレートエンジンです。
Jbuilderを利用するときは、コントローラ内でrender json: ○○を行いません。

jbuilderを使用して、作成したメッセージをJSON形式で返す

respond_toで処理を分けたら、jbuilderを使用してJavaScriptファイルに返すデータを作成します。
jbuilderは、viewと同じように該当するアクションと同じ名前にします。
commentのcreateアクションに対応するjbuilderのファイルになるので、作成するのはviews/comments/create.json.jbuilderになります。
【例】今回はコメント欄にtextとuser.idとuser.nicknameがあるとします。

views/comments/create.json.jbuilder
json.text  @comment.text
json.user_id  @comment.user.id
json.user_name  @comment.user.nickname

jbuilderファイルでは基本的にjson.KEY VALUEという形で書くことができます。
こうすることによってJavaScriptファイルに返ってきたデータをjbuilderで定義したキーとバリューの形で呼び出して使うことができます。

返ってきたJSONをdoneメソッドで受取り、HTMLを作成する

非同期通信の結果として返ってくるデータは、done(function(data) { 処理 })の関数の引数で受け取ります。

comment.js
$(function(){
  function buildHTML(comment){   #追加〜
    var html = `<p>
                  <strong>
                    <a href=/users/${comment.user_id}>${comment.user_name}</a>
                    :
                  </strong>
                  ${comment.text}
                </p>`
    return html;
  }   #〜追加
  $('#new_comment').on('submit', function(e){
    e.preventDefault();
    var formData = new FormData(this);
    var url = $(this).attr('action');
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: 'json',
      processData: false,
      contentType: false
    })
    .done(function(data){   #追加〜
      var html = buildHTML(data);
      $('.comments').append(html);
      $('.textbox').val('');
      $('.form__submit').prop('disabled', false);
    })   #〜追加
  })
});

.done〜は、非同期通信に成功した時の記述です。function(data)となっていますが、非同期通信に成功した時の即時関数の第一引数には、サーバから返されたデータが入っています。この場合のサーバから返ってくるデータというのは、jbuilderで作成したcreate.json.jbuilderのデータです。
$('.form__submit').prop('disabled', false);は、 htmlの仕様でsubmitボタンを一度押したらdisabled属性というボタンが押せなく属性が追加されます。
そのため、disabled属性をfalseにする記述を追加しています。
function buildHTML(comment){〜はHTMLを追加しています。

テンプレートリテラル記法

ダブルクオートやシングルクオートの代わりにバックティック文字(`)で囲むことで、複数行文字列や文字列内挿入機能を使用できます。
buildHTMLの引数として渡されたcommentはサーバから返されたデータであるjbuilderのデータであるため、ファイル内で定義したキーとバリューの形式で使用できます。

エラー時の処理を行う

comment.js
〜省略〜
.done(function(data){
      var html = buildHTML(data);
      $('.comments').append(html);
      $('.textbox').val('');
      $('.form__submit').prop('disabled', false);
    })
    .fail(function(){   #追加〜
      alert('error');
    })  #〜追加
〜省略〜

失敗した場合の処理で、アラートを表示します。

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