Tanaka on Rails

行動・努力・俯瞰

Rail 7 - SorceryからDeviseへ苦渋の決断

ユーザー機能はSorceryの方がイイ!と思っていたが...

Railsのユーザー機能を便利に設定できるGemとしてSorceryとDeviseが二大勢力だと思われます(検索した感じはDeviseの方が圧倒的に強いが)。
これまで学習してきた中では融通が効くと認識よりSorceryしか使用したことがなく、当然のごとくアプリケーション制作においてもSorceryを使用してユーザー機能を作成したのですが、1つ大きな壁にぶち当たりました。

SorceryはLINEログインを使用できない!?

僕が開発しているアプリケーションではLINEmessagingAPIを使用する予定なのですが、どうやらSorceryではLINEログインができないっぽいです!
調べていくとSorceryでモンキーパッチ(外部ライブラリの挙動を、動的に拡張する仕組み)を設定してLINEログインできるようにすることもできるようですが、あまりそれは好ましくないとのこと。

bagelee.com

techlife.cookpad.com

LINEログインを行うためにはDevise+Omniauth(別の記事で触れる予定)が常道らしいので手間はかかりますが変更を行うことにしました。
なお軽く検索にかけたところそういった変更をするケースの記事がなかったので(そもそも間違えて使用したりはしない?)まとめていきたいと思います。

手順①既存のSorcery関連のファイルを削除

$ rails d sorcery:install

をすると...

remove  config/initializers/sorcery.rb
generate  model User --skip-migration
rails  generate model User --skip-migration 
subtract  app/models/user.rb
subtract  app/models/user.rb
remove  db/migrate/20211126231040_sorcery_core.rb

といったファイルが削除&修正される。
そしてGemfileよりsorceryを削除し$ bundle install。 ただこの状況だとSorceryのマイグレーションファイルがなくなっているのにdb/schema.rbには全く変更がない状態です。
なので面倒にはなりますがUserテーブルを一度削除します。

手順②外部キー設定を解除する

僕のケースではTaskというモデルが存在していてuser_idという外部キーを持ちアソシエーション関係にあるため、ここから修正しないとUserテーブルを削除できない(しようとするとエラーになります)。

$ rails g migration remove_user_from_task

をしたらマイグレーションファイルの内容を...

class RemoveUserFromTask < ActiveRecord::Migration[6.0]
  def change
    remove_reference :tasks, :user, null: false, foreign_key: true
  end    
end

として

$ rails db:migrate

するとアソシエーション関係が解消するためUserテーブルを消すことができる。

qiita.com

手順③Userテーブル削除

$ rails g migration drop_user

としてマイグレーションファイルを

class DropUser < ActiveRecord::Migration[6.0]
  def change
    drop_table :users do |t|
      t.string "email", null: false
      t.string "crypted_password"
      t.string "salt"
      t.datetime "created_at", precision: 6, null: false
      t.datetime "updated_at", precision: 6, null: false
      t.index ["email"], name: "index_users_on_email", unique: true
    end
  end
end

として...

$ rails db:migrate

これでUserテーブルが消せた!

qiita.com

Deviseの設定

これでUserテーブルのない素の状態になったので、通常通りにDeviseを導入できる(とはいっても僕は使うのが初めて😅)。

$ rails g devise:install

すると

Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"
     
     * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views
       
     * Not required *

と出るのでとりあえず命令通りに1だけ設定。
そして

$ rails g devise User

とするとマイグレーションファイルができるのでとりあえずそのまま

$ rails db:migrate

をする。そうすると
db/schema.rb

  create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

とDevise式のUserテーブルができていることがわかる。

http://localhost:3000/users/sign_upに行ってみると...
Image from Gyazo

みたいな感じでパッケージングしてくれたページを作成してくれる、これがDeviseか!
ちなみに$ rails g devise:installの時の導入を1しかやってないのでこんな感じで最低限の感じで表示されているのだと思う。

Userテーブルにプラスでカラムをつけたい場合は各々$ rails migration ~で作成をしていきましょう。

www.sejuku.net

次回に続くよ

ただこれをそのまま使用するのは僕のアプリケーションにはそぐわない。
なのでこれからVueでJWT認証をDeviseでできるようにしていく。

Rail 6 - 時間ロジック

Railsにおける時間のロジック

Railsで時間を計測する機能を実装中なのですが、その中で学んだことを書いていきます。

フロントエンドはVue.jsでの実装をしており、以下のサイトが非常に参考になりました。

note.com

qiita.com

問題はRailsの方。
スタートした時間をstart_at、ストップした時間をend_atといったカラムを使って保存し、その差によってかかった時間をtake_timeのようなカラムに保存して時間を計測するロジックを考えていました。

ただそれで問題となるのはカラムの型。
start_atend_atはDatetime型で問題なし。

qiita.com

www.fundely.co.jp

take_timeはどうするか?
初めはTime型を使用していたのですが、保存されるときに「協定世界時(UTC)の1970年1月1日午前0時」から起算されるので、日本で登録すると「1970年1月1日午前9時」に登録されるようでした。
これだと単純に何分とか何秒とかの計算で使用するならいいかもしれないですが、何時間とかともなると午前9時というのがめちゃくちゃ邪魔になります笑

それに加えてend_atからstart_atを引いた差は1.423...といった小数点まで含む秒数として計算されるので、これを保存するという意味でもTimeだと変形しないといけないので不便だと思いました。

そこで単純に数値として小数点まで保存できるFloat型を暫定で採用しようと思っています。
これを使えば計測時間をVue側で表示をする場合は計算をしないといけませんが、単純にRails側で保存するという点ではスッキリします。

現状ではこの方法で実装していこうと思っていますが、まだ開発中なのでもっといい方法があれば改善していこうと思っています!!

Rail 5 - TailwindCSS再び・Bullet

Tailwind CSSの導入

yarnで導入する際は以下を参照。

qiita.com

その後にデプロイする際にCSSファイルをpurgeする必要あり。⚠️要チェック

qiita.com

Gemで導入もできるが、比較的リリースが新しくて情報が少ないのと、Webpackerにまとめるにはyarnでのインストールの方がいい?感じがするのでアプリケーション開発にはyarnでの導入を検討。

gem 'bullet'

N+1問題が生じた際にブラウザに注意メッセージを表示してくれるらしい。
便利そう!

techtechmedia.com

Rail 4 - pry-byebug・YarnとWebpacker

gem 'pry-byebug'

デバック用のGem。
これまではデフォルトで使用できるbinding.irbを使用していたが、nextなどのコマンドを使えるbinding.pryを使った方が便利そう。

github.com

qiita.com

techtechmedia.com

Yarn

Javascriptのパッケージマネージャ。
npmより高速、yarn.lockというバージョンロック機構あり。

$ yarn add パッケージ名

によりpackage.jsonにパッケージを追加する。
インストールしたパッケージはnode_modulesディレクトリに配置される。

qiita.com

Webpacker

webpackなどのフロントエンドビルドシステムの目的は、開発者にとって使いやすい方法でフロントエンドのコードを書き、そのコードをブラウザで利用しやすい方法でパッケージ化することです。webpackは「JavaScript」「CSS」「画像やフォント」といった静的アセットを管理できます。webpackを使うと、「JavaScriptコードの記述」「アプリケーション内の他のコードの参照」「コードの変換(トランスパイル)や結合」をダウンロードしやすいpackにまとめられます。
Rails Guides

同様のRailsでの静的アセット管理にSproketsがあるがどちらを使うか?

新しいプロジェクトで「NPMパッケージを使いたい場合」「最新のJavaScript機能やツールにアクセスしたい場合」は、Sprocketsではなくwebpackerを選択すべきでしょう。「移行にコストがかかるレガシーアプリケーション」「gemで統合したい場合」「パッケージ化するコードの量が非常に少ない場合」は、WebpackerではなくSprocketsを選ぶべきでしょう。
Rails Guides

Vue.jsを導入するときは

$ rails webpacker:install:vue

とすればOK。

qiita.com

参考

www.amazon.co.jp

techracho.bpsinc.jp

Rail 3 - Rails new・TZinfo-data・Tailwind CSS

Rails newに関するエラー

$ rails _6.0.4_ new 

を実行した際にcan't find gem railties (= 6.0.4) with executable rails (Gem::GemNotFoundException)というエラーが出た。
初めは下記サイトを参考にして

$ rbenv exec gem install bundler #bundlerをローカルにインストール
$ rbenv rehash #~/.rbenv/shims/にコピー

としたが同じエラーが出た。
Rubyのバージョンを変えても同じ。

`find_spec_for_exe': can't find gem railties (>= 0.a) with executable rails (Gem::GemNotFoundException)が発生した時 - Qiita

改めてエラー読み直すと単純にローカルにRails 6.0.4のバージョンがインストールされていなことに気づいた。

$ gem list rails #Rails 6.0.4が入っているか確認  
$ gem install rails -v 6.0.4 #ない場合はインストールする  

RubyとRailsのバージョンの変更方法 - Qiita

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

TZinfo-dataはTZInfoが参照するタイムゾーン情報を提供するgem。 TZInfoはRubyからタイムゾーン情報を参照し、その情報に基づいて時間をコンバートするためのライブラリ。
rails newするとデフォルトでインストールされる。

bundle installする際のtzinfo-dataのwarningがウザい - Qiita

Tailwind CSS

アプリ開発にあたって、自由度が高いことや簡潔にかけることなどを加味してTailwind CSSの使用を検討しています。
以下に便利そうなサイトをまとめました。

Tailwind Play

wickedblocks

TailwindTemplates

Rail 2 - AWSのSSHログイン

AWSによるデプロイ注意点

この教材AWSのデプロイの仕方を学びました。
その中でいくつか躓いたことがあったのでまとめました。

sshAWSでログインする際にclient_loop: send disconnect: Broken pipeと表示されログインできない

cd .sshvim configをして

IPQoS 0

を加筆。
参考
https://7ka.org/cant-connect-ssh-macos/

sshAWSにログインする際にPermission denied (publickey,gssapi-keyex,gssapi-with-mic).と表示されログインできない

これについてはssh -vvv testでログを見ても原因がわからず。
権限の問題かと思いchmod 600 〇〇をしたりしても同じ表示がされてしまった。
結局原因は分からなかったが以下のことをしたら入ることができるようになったのでメモしておく。
AWSのEC2のインスタンスの画面で「接続」→「接続」をすることで、ブラウザ上でターミナルを起動。そして少しそのターミナルで作業をしたのちにログアウトする。
なぜこれでログインできるようになったのかは不明。

Rail 1 - Dockerコマンド

Dockerよく使用するコマンド

現在の状況を確認

$ docker images

イメージ確認

$ docker image rm イメージ名

イメージ削除

$ docker ps

現在稼働しているコンテナ確認

$ docker stop コンテナ名

コンテナ停止

$ docker ps -a

現在存在するコンテナ確認

$ docker rm コンテナ名

コンテナ廃棄

参考

以下の本で学習中

www.amazon.co.jp