ume

rails7 from_withのオプションの違い(model:オプションとurl:オプション)

結論

フォームのデータをコントローラーでparams[:モデル名][:キー]でデータを受け取るかparams[:キー]で受け取るかの違い

modelオプション

⇨params[:モデル名][:キー]でデータを受け取る

urlオプション

⇨params[:キー]でデータを受け取る

modelオプション

例 

 <%= form_with model: CartProduct.new do |f| %>
  <%= f.number_field :quantity, class: "form-control text-center me-3", style: "max-width: 4rem", min: 1, max: 100%>
省略
<% end %>

modelオプションでモデルのインスタンス(@cart_productなど)を渡すかModel名.newで設定すると.
コントローラー内で

params{
 "cart_product"=>{"quantity"=>"4"}
}

このようになります。 paramsの中に[:モデル名][:key]のようになります.

urlオプション

 <%= form_with url: "/cart_products/1" do |f| %>
  <%= f.number_field :quantity, class: "form-control text-center me-3", style: "max-width: 4rem", min: 1, max: 100%>
省略
<% end %>

このようにurlで指定すると

params{
{"quantity"=>"4","id"=>"1"}
}

このようになります。modelオプションの時とは違い[:model名]が入らずにシンプルになります。またform_with url: "/cart_products/1" do |f| %>で設定した/cart_products/1の1の部分が{id:1}のようにparamsの中に格納されます

まとめ

modelオプションもurlオプションもしていることは指定したサーバーにフォームのデータを送ることが目的ですが、それぞれparamsの中の中にデータを入れる方法が異なることがわかりました。

Rails7メンターさんにしていただいたこと(Active StorageのN+1問題)

前書き

現在ECサイトを作成しています。

以下のコードで上記の表示をしています.
index.html(↓わかりやすいように余計なdivタグなど省略).
products_controller.rb

class ProductsController < ApplicationController
  def index
    @products = Product.all   #productテーブルからデータを全て取得
end 

index.html.erb

<% @products.each do |product| %> #Productテーブルのデータを一つずつ取り出す(みかんなど)
<%= link_to product_path(product.id)  do %>
 <%= image_tag product.image,class:"w-100 h-100", style:" aspect-ratio: 2 / 1;"   if product.image.attached? %>#product.imageでproduct(みかんなど)の関連データ(みかんの画像など)を取得表示する
<% end %>
<% end %>

データベースには Productテーブルに商品に関するデータが入っておりblobテーブルには商品に関連のある画像が格納されている

指摘箇所

Products_controller.rb

class ProductsController < ApplicationController
私のコード↓
  def index
    @products = Product.all
  end
メンターさんに↓のように修正するようにと言われました。
  def index
    @products = Product.with_attached_image
  end
end

解説(なぜこのように修正する必要があるか)

⇨N+1問題を解決するため

N+1問題とは?

shuttodev.hatenablog.com

https://pikawaka.com/rails/includes

N+1問題を一言でいうと「無駄にSQLが発行される」状態

どういう時にN+1問題が発生する?

⇨モデルオブジェクト.関連名.

関連名とは?

models/product.rbファイル

class Product < ApplicationRecord
  has_one_attached :image #⇦ここが
関連名
end 

下のコードを実行するとN+1問題発生する

@products = Product.all
@product.each do |product|
product.image  #⇦ここで無駄なSQLが発行される
end 
 解決策(active storageを使用している場合)

⇨ with_attached_imageメソッドを使う

@products = Product. with_attached_image

まとめ

  • N+1問題とは無駄なSQLを発行してしまう問題

  • モデルオブジェクト.関連名で発生する

正規表現を翻訳

前書き

下記の正規表現の意味を一つ一つ分解し理解を深める

/\A(?=.*\d)(?=.*[a-zA-Z])[a-zA-Z0-9]+\z/

\A

⇨先頭文字を評価

()

→グループ化. 評価する文字に()内で指定した複数文字をがあるか調べる.
例(じゃ)+ーん.
マッチする文字

じゃじゃーん
じゃじゃじゃーん

+は直前の一文字以上が評価する文字にあるのか調べる.
例じゃ+-ん⇨「ゃ」が一文字以上あるのか調べる

?

⇨直前の文字がないか、1つだけある.
Windows?
マッチする値

window 
windows

例 wind?ows マッチしない

winddows

.

→一文字だったらなんでも良い マッチしない例がなぜいけないかというと

saru 先頭がzではない
maru 先頭がzではない
zau 文字数が足りない

*

アスタリスクの前の文字(u)が評価する文字の中になくてもいいし1文字以上あってもいい

例. maru*にマッチするかどうかを調べる

マッチする例

mar  #アスタリスクの前のuが評価する文字(mar)の中になくてもいい
maruuuuuuuuuu #アスタリスクの前のuが評価する文字(mar)の中に一文字以上あってもいい

マッチしない例

mavu

\d

⇨半角数字

例 3 マッチする例

342142

マッチしない例

12314

⇨はブランケットという。[]内の文字や数字にマッチするか調べる.
例 [a].
マッチする例

a  
aaaaa

マッチしない例

b
1

-を使うことで範囲を示す.
例. [a-z] ⇦a~zまでのアルファベットにマッチするか調べる.
マッチする例

b
cb

マッチしない例

1
23

+

⇨+の直前の文字(u)が評価する文字の中に一文字以上ある.
例 maru+.
マッチする文字

maru #評価する文字(maru)の中にuが入っているのでマッチする
maruuuuuuu #評価する文字の中に一文字以上uがあるのでマッチする

マッチしない文字

mar
marf

\z

⇨\z 文字列の末尾にマッチします.
⇨\Z 文字列の末尾にマッチします。 ただし文字列の最後の文字が改行ならばそれの手前にマッチします.
要は語尾が改行だったら改行を評価するのが\zで開業の直前まで評価するのが\Z

# 末尾が改行文字、正規表現は小文字の \z
"03-1234-5678\n" =~ /\A\d+-\d+-\d+\z/
# => nil (Rubyの世界では偽)

# 末尾が改行文字、正規表現は大文字の \Z
"03-1234-5678\n" =~ /\A\d+-\d+-\d+\Z/
# => 0 (Rubyの世界では真)

参考情報

https://www.youtube.com/watch?v=T7Y2kfMm7kk

regex-checker.com

rails7 ルーティングの記載の順番で挙動が変わる件について

前書き

正しいルーティングを記載しているのに想定していたコントローラーに繋がらなくハマったので記事に残します。

ハマったこと

new_admin_product(admin/products#new ) というprefixでリクエストを送るとBのadmin/productsコントローラーのnewアクションに遷移すると想定していました。ただ実際はAのproductsコントローラーのshowアクションに遷移してしまう。 上記のルーティングで実際作成されるパスは以下になります↓

| ルート名            | HTTPメソッド | パス                         | コントローラー#アクション   |
|---------------------|--------------|------------------------------|-----------------------------|
| admin_products      | GET          | /admin/products(.:format)    | products#index              |
| admin_product       | GET          | /admin/products/:id(.:format)| products#show  ⇦このアクションにつながる             |
|                     | POST         | /admin/products(.:format)    | admin/products#create      |
| new_admin_product   | GET          | /admin/products/new(.:format)| admin/products#new ⇦このアクションにつなげたい       |
| edit_admin_product  | GET          | /admin/products/:id/edit     | admin/products#edit      |
|                     | PATCH        | /admin/products/:id(.:format)| admin/products#update      |
|                     | PUT          | /admin/products/:id(.:format)| admin/products#update      |
|                     | DELETE       | /admin/products/:id(.:format)| admin/products#destroy     |

結論

⇨namespace :admin doとscope 'admin' doのルーティングの記載の順番を入れ替える

| ルート名            | HTTPメソッド | パス                             | コントローラー#アクション   |
|---------------------|--------------|----------------------------------|-----------------------------|
| admin_products      | POST         | /admin/products(.:format)        | admin/products#create      |
| new_admin_product   | GET          | /admin/products/new(.:format)    | admin/products#new ⇦このアクションにつながる    |
| edit_admin_product  | GET          | /admin/products/:id/edit.        | admin/products#edit        |
| admin_product       | PATCH        | /admin/products/:id(.:format)    | admin/products#update      |
|                     | PUT          | /admin/products/:id(.:format)    | admin/products#update      |
|                     | DELETE       | /admin/products/:id(.:format)    | admin/products#destroy     |
|                     | GET          | /admin/products(.:format)        | products#index              |
|                     | GET          | /admin/products/:id(.:format)    | products#show               |

解説

new_admin_product(/admin/products/new) というリクエストを送信するとroutes.rbの上から順番に一致するものを探す

| ルート名            | HTTPメソッド | パス                         | コントローラー#アクション   |
|---------------------|--------------|------------------------------|-----------------------------|
| admin_products      | GET          | /admin/products(.:format)    | products#index              |
| admin_product       | GET          | /admin/products/:id(.:format)| products#show  ⇦このアクションにつながる             |
|                     | POST         | /admin/products(.:format)    | admin/products#create      |
| new_admin_product   | GET          | /admin/products/new(.:format)| admin/products#new ⇦このアクションにつなげたい       |
| edit_admin_product  | GET          | /admin/products/:id/edit     | admin/products#edit      |
|                     | PATCH        | /admin/products/:id(.:format)| admin/products#update      |
|                     | PUT          | /admin/products/:id(.:format)| admin/products#update      |
|                     | DELETE       | /admin/products/:id(.:format)| admin/products#destroy     |

上のハマったルーティングを見ると /admin/products/newが/admin/products/:idと一致すると判断されたため想定外のコントローラーのアクションに遷移しました.
なぜなら:idの中にnewが代入される. :idと聞くとadmin/products/2などのように数値 が入るイメージでしたが数値以外も代入されるそうです

まとめ

  • ルーティングの記載の順番で想定外のコントローラーにつながる

  • /admin/products/:idなどの:idには数値以外も代入される

  • ルーティングは上から順番に一致するものを探す

rails7 データベース string型とtext型の文字制限のバリデーションについて

前書き

以下のnameカラム(string型)とdscriptionカラム(text型)にlengthのバリデーションは必要?また必要なら何文字で設定するのがいいの?という2つの疑問が湧いたので忘却録として記事に残します ↓migrationファイル

結論

⇨人それぞれの用途でlengthのバリデーションの有無や文字数の制限を設定する。

そもそもstringとtextの違いは?

データ型 データベースに登録できる文字数
string 255文字まで
text 上限なし
それぞれの用途
  • string⇨一言入力したいときなどに使う。(名前、電話番号、住所など).
    バリデーション必要.
    理由 おかしな文章を登録できないようにするため(ポスグレの場合).
    ポスグレでstring型で255文字を超えて登録しようとすると256文字以降の文字は登録されない。

例256文字を登録しようとした時

省略
ありがとうございます

上記のありがとうございますの「す」が256文字目だとすると「ありがとうございま」までしかポスグレには登録されない。

  • text⇨長文投稿したいときなどに使う。(コメント、ブログなど)

バリデーション必要なし 下記のサイトを見るとデータ型にあまり違いがないので長文の文字列を登録する際場合はtext型でバリデーションなしで問題ないと思います。 teratail.com

www.postgresql.jp

まとめ

  • 文字制限したいカラムにはstring型を使う。

  • 文字制限する必要がない場合はtext型を使う

参考情報

qiita.com

javascript エンジニアが実務でよく使うjsのMathオブジェクト

目次

  1. Math.random()

  2. Math.round(数値)

  3. Math.ceil(数値)

  4. Math.floor(数値)

1. Math.random()

⇨0~1までのランダムの数値を作成します。

console.log(Math.random())
#出力結果 0.04764646236311276

1. Math.round(数値)

⇨四捨五入する

console.log(Math.round(1.6))
#出力結果2

Math.ceil(数値)

⇨対象の数値の小数点以下を切り上げ

console.log(Math.ceil(1.4));
#結果2

Math.floor(数値)

⇨対象の数値の小数点以下を切り捨てます

console.log(Math.floor(1.6)); // 1.6を切り捨て、1となる