RailsにJSを書く前に、yarn, npm, webpack, webpacker, ES6を理解する。

  • npmを便利にしたものが、yarn

  • JSは、ES5からES6へ。クラスやアロー関数などが使えるようになった。(babelで変換可)

  • 上記のファイルの依存関係等をいい感じにまとめてくれるのが、webpackで、Railsにフィットさせるためのwebpackerというのがある。

npm

JavaScript(正確にはNode.jsモジュール)のパッケージマネージャです。言ってみれば、JavaScript世界におけるRubygemです。

npm = rubyでいうgem

npm install bootstrap

npmは、ダウンロードしたパッケージを./node_modulesに保存し、パッケージのリストを./package.jsonに保存します

yarn

npmよりずっと高速です。

npmより新しいパッケージマネージャです。yarnはnpmのリポジトリからパッケージを取得する点は同じ

ES6

クラス、アロー関数などでJSが書けるようになった

Babel

全てのブラウザでES6が動くわけではないので、EC5に変換するためのファイル。

Webpack

yarn, npm es5,es6などの依存関係を綺麗にまとめるもの。

webpacker

RailsアプリケーションにWebpackをいい感じに取り込めるgem

ルール

  • application.jsは、app/javascript/packs配下に置かれる。

  • viewにjsをincludeするには、

view
<%= javascript_pack_tag 'pages/index' %>

↓

app/javascript/packs/index.js
//ここにjsを書く。

参考;

https://techracho.bpsinc.jp/hachi8833/2020_01_16/85940

Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 後編(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

webpack

Webpackerを使ったRailsでのJavaScript開発 - クックパッド開発者ブログ

webpack学習の基本のき

Mysql2::Error: Table 'myapp_development.post_tags' doesn't exist のエラー解決

背景

postを削除しようとしたら、このエラーが起こった。

解決のプロセス

mysqlのテーブルを見てみる

mysql> use myapp_development
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------------------+
| Tables_in_myapp_development |
+-----------------------------+
| ar_internal_metadata        |
| comments                    |
| impressions                 |
| likes                       |
| posts                       |
| posts_tags                  |
| relationships               |
| schema_migrations           |
| tags                        |
| users                       |
+-----------------------------+
10 rows in set (0.01 sec)

mysql>

schembaを見てみる

create_table "posts_tags", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.bigint "post_id", null: false
    t.bigint "tag_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["post_id"], name: "index_posts_tags_on_post_id"
    t.index ["tag_id"], name: "index_posts_tags_on_tag_id"
  end

post_tagsを削除しようとしているのはなぜ?

これが原因だった。

post.rb
has_many :post_tags, dependent: :destroy

以前、タグを新しいテーブルを作成し、改良したときに、古いテーブルを消し忘れていた事が原因だった。

mysql8.0のエラー Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

MySQL5.7までの認証プラグインには mysql_native_password がデフォルトで使用されていましたが、MySQL8.0より新たに追加された caching_sha2_password

プラグインがもともとコードに書かれていたのに無いと言うことは、migrateとかをすればいいと思う。

http://blog.s-style.co.jp/2018/05/1807/

・新規dockerfileに以下を追加する

FROM ruby:2.6

WORKDIR /tmp
RUN apt update && apt install -y lsb-release \ 
    && apt remove -y libmariadb-dev-compat libmariadb-dev

RUN wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-common_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/libmysqlclient21_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-client-core_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-client_8.0.18-1debian10_amd64.deb \
    https://dev.mysql.com/get/Downloads/MySQL-8.0/libmysqlclient-dev_8.0.18-1debian10_amd64.deb

RUN dpkg -i mysql-common_8.0.18-1debian10_amd64.deb \
    libmysqlclient21_8.0.18-1debian10_amd64.deb \
    mysql-community-client-core_8.0.18-1debian10_amd64.deb \
    mysql-community-client_8.0.18-1debian10_amd64.deb \
    libmysqlclient-dev_8.0.18-1debian10_amd64.deb

nginxをdockerから起動したら、エラーが消えた。

参考

taker.hatenablog.com

github.com

Pumaについて

bindle exec puma -d

指定する場合

bundle exec puma -C config/puma.rb

pumaはサーバのソケットを開いたままリスタートできます。要するに、ユーザーに対してサーバを開放したままサーバのリスタートができるということです。ユーザーを待たせることがないため、pumaを速くすることに貢献しています。

hot resrartと呼ばれるやつ

停止

kill -SIGUSR2 `(cat tmp/pids/server.pid)`

or

bundle exec pumactl restart

https://arma-search.jp/article/ruby-puma#i-2

ソケットとは?

pumaの設定

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
#{myapp_root}/tmp/sockets/puma.sock に bind している
bind "unix://#{myapp_root}/tmp/sockets/puma.sock"

「environment」

pumaをどの環境で動作させるかを指定します。デフォルトは'development'になっています。

「daemonize」

rackサーバーをデーモンにして起動するかどうか

pidfile」

pidファイルを配置するパスを指定します。 tmp/pids/puma.pidに配置するほうが良いと思います。

state_path」 サーバー情報を記載したstateファイルを配置するパスを指定します。 stateファイルはpumactlコマンドでサーバーを操作するのに使用します。 railsの場合、特別このようなファイルを配置するディレクトリはないので今回はtmp/pids/以下に配置

「Cluster mode」

クラスタモードとは複数のワーカープロセスを起動し、そのプロセスそれぞれでスレッドプールを持ちリクエストを処理する仕組みです。 ワーカープロセスの数は以下のように指定します。 Workerの数をマシンが持つCore数を超えないように気をつけて下さい。

「Thread Pool」 Pumaはスレッドによってリクエストを処理します。スレッドをスレッドプールに貯めておく数の下限から上限を指定することが出来ます。

「bind」 サーバーをどのように接続するかをURIで指定。シンプルにTCPで接続する場合tcp://0.0.0.0:80、またWebサーバーの前段にnginxをなどを置き、そこからUNIX Socket経由で接続する場合はunix:///var/run/puma.sockのように指定します。 f:id:kaz08:20210301104547p:plain

なんでNginxを使うのか、高速化と処理の負担を分散させる。

Nginx: 静的,画像を処理

↓↑UNIXドメインソケット(unix://の意味はこれか。)

Pumaは動的なファイルの処理に集中できる


スタートしてみた

# bundle exec puma
Puma starting in single mode...
* Puma version: 5.1.1 (ruby 2.6.6-p146) ("At Your Service")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 36

ハンズオン

nginxとpumaの設定、連携が書かれていてわかりやすい。

Mac1台にnginxでWebサーバとPumaでアプリサーバを立てる

binding.pry使い方

知らなかったこと:
処理を止めたコントローラーで、コンソールから変数を入力すると、定義されていれば値が帰ってくる。定義されていなければ、nilが帰ってくる。

viewでも実行できる

<%= @book.title %>
<% binding.pry %>

これで、@book.title内に本当に正しい情報が入っているか確かめることができる。

デバックを使って学習することができる

@books.methods

これを実行したら、使えるメソッドが大量に出てくる。

[4] pry(#<#<Class:0x000055eb1296c988>>)> @posts_get_likes.methods
=> [:per,
 :max_paginates_per,
 :total_pages,
 :padding,
 :current_page,
 :next_page,
 :out_of_range?,
 :current_per_page,
 :last_page?,
 :prev_page,
 :first_page?,
 :offset_value,
 :limit_value,
 :offset_value=,
 :limit_value=,
 :limit,
 :page,
 :total_count,
 :offset,
 :entry_name,
 :max_per_page,
 :paginates_per,
 :max_pages,
 :max_pages_per,
 :default_per_page,
 :to_json,
 :third,
 :fourth,
 :fifth,
 :forty_two,
 :third_to_last,

<page break> --- Press enter to continue ( q<enter> to break ) --- <page break>

 :second_to_last,
 :to_h,
 :including,
 :excluding,
 :without,
 :include?,
 :compact_blank!,
 :pretty_print,
 :at,
 :fetch,
 :last,
 :union,
 :difference,
 :push,
 :append,
 :pop,
 :shift,
 :unshift,
 :each_index,
 :join,
 :rotate,
 :rotate!,
 :sort!,
 :sort_by!,
 :collect!,
 :map!,
 :select!,
 :filter!,
 :keep_if,
 :values_at,
 :delete_at,

<page break> --- Press enter to continue ( q<enter> to break ) --- <page break>

 :delete_if,
 :reject!,
 :transpose,
 :fill,
 :assoc,
 :rassoc,
 :uniq!,
 :compact,
 :*,
 :+,
 :flatten!,
 :&,
 :shuffle,
 :sample,
 :compact!,
 :flatten,
 :combination,
 :shuffle!,
 :-,
 :repeated_permutation,
 :sort,
 :product,
 :bsearch,
 :repeated_combination,
 :count,
 :blank?,
 :find_index,
 :to_param,
 :select,
 :filter,
 :reject,
#以下省略

Dockerを使っている場合

docker attach コンテナ名

ゲストユーザーを編集させない

はじめに

編集ボタンを隠すやり方もあるが、"編集画面を作っている"と、ポートフォリオを見る人へ伝えたかったので、編集ボタンを表示させて、それを押したら→リダイレクト→「ゲストユーザーは編集できません」のメッセージを表示。というやり方で実装しました。

前提:

ゲストユーザーのpathは'users/2'とする。編集は、'users/2/edit'。
email: smooth_login@example.com

もし、user/showにあるユーザー画面で、プロフィール編集ボタンを押してきた場合

router

ゲストログインを、smooth_loginと表していたため、smoothとルートを定義しました。

get '/smooth' => 'users#smooth', as: 'smooth_edit'

controller

def smooth
    flash[:danger] = "簡単ログインしたユーザーは編集できません。"
    redirect_to request.referrer || 'users/2'
  end

view(作らなくてもmethod: :getでいけるかも。。)

smooth.erb.html

#空

もし、'users/2/edit'と直接リンクを打たれた場合

user/edit.html

<% if @user.email == "smooth_login@example.com" %>
<p>ゲストユーザーは編集できません</p>
<%= link_to :back do %>
  <button>戻る</button>
<% end %>
<% else %>
##ここに通常の編集コード
 <% end %>

最後に

もっといいやり方があるかもしれません。