高速に開発するために
・とりあえず、適切なブランチに移動し、コントローラーとViewファイルを開くor用意する
アプリ作成時の手順
- 仕様を決める
- DB構成を決める
- システム構成(サーバー、外部サービスなど)を決める
- Railsアプリをセットアップ
- モデルとDBを作成
- モデルのテスト、ファクトリを作成
- 画面表示に必要なcontroller、viewを作成
- routingを作成
- Sassの構成を決定
良いコードを書くために
・可能な限り処理をモデルのメソッドに切り出し、コントローラーを薄くする
・view内のロジックはhelperに逃がす
・jsはページごとのjsファイルを作ってそこに書く
・パーシャルを使い、可読性と再利用性を上げる
・住所など、繰り返し使う文字列はlocaleにまとめる
・日付をformatするとき、strftime
メソッドを書かずにl
メソッドとlocaleを活用するとDRYなコードになる
【初心者向け・動画付き】Railsで日時をフォーマットするときはstrftimeよりも、lメソッドを使おう
・ネストを減らす
・最初は取っつきづらくても、出来るだけ短い書き方に慣れていった方が良い
好きなところ
・文字列の中に変数を含ませたいとき、"こんにちは#{name}さん"
って式展開ができて、余計な.
とか+
とかが無くて良い
・引数や条件式に()
をつけなくて良い
・文末に;
が無くて良い
・ブロックを{}
で囲まなくて良い
・nil
が偽として扱われるので、条件式がスッキリする
・for文をarray.each do |n|
で代用している
・ORマッパー
・resourcesでルーティングが一気に出来上がる
・gemが豊富
・link_toにdata: {confirm: "削除しますか?"}をつけると、リンク先に遷移する前にコンファームを表示することができる。
・配列の末尾にデータを追加する時の書き方customers << record
が直感的
好きじゃないところ
・過去に色々変更があったみたいで、古い情報を見ると今は推奨されていない書き方だったりする
・Webpackerが迷走してるっぽい。JSのベストプラクティスがいまいちわからない
忘備録
・URLのパラメーターはparams[:id]
、フォームで入力されたパラメーター(strong_parameterを通す)はtask_params
とかで出力
・migrationファイルを作る時、コマンドラインでstring
を省略できる。
(rail g migratinon name age:integer
)
・resources
でルーティングを作って、showアクションを指定しなかった場合、updateアクションの後に戻るボタンを押すとshowアクションにルーティングされてエラーが発生する。
→404ページに遷移させることができないので、showアクションのルーティングは消すべき。そもそもshowアクションを作った方が良いかも。
・link_to
にdata: {confirm: "削除しますか?"}
をつけると、リンク先に遷移する前にコンファームを表示することができる。
例:<%= link_to '削除', admin_email_path(i), method: :delete, data: {confirm: "削除しますか?"}, class: "-delete" %>
Railsでdata-confirmを使ってデータ削除時にアラートを表示する
・carrierwaveのprocess resize_to_fill
を使って、指定した比率の画像を取得する時、小さい値を入れると画像がぼやけがちなので、少し大きめのサイズを指定すると良い。
(元画像より小さい値が指定されてる場合にぼやける)
関連:CarrierWave + RMagick 画像のリサイズをまとめてみました
・form_with
で非同期通信をした時に、画面の位置を動かしたくなかった。redirect_to hoge_path(anchor: "hogeid")
とアンカーリンクをつけて試みたところ、アンカーリンクの内容に関わらず位置が動かなくなった。
→anchor
オプションをつけるだけで動かなくなるのか?
・each.with_index(1)
で、eachの中に1から始まるインデックスを表示することができる。
rubyでeach_with_indexでindexの値を0以外から始める方法
・新たにテーブルを作成する時、migrationファイル内の:string
を省略できるが、後からフィールドを追加する時には省略できない。
・redirect_to hoge_url, notice: '成功しました'
という書き方で、リダイレクトとflashメッセージを同時に記述することができる。
・success: '成功しました'
= flash: {notice: '成功しました'}
値が1つしか無いハッシュは、親と括弧を省略できる。
・redirect_to
の引数に設定できるflashはnotice
とalert
だけ。success
とかオリジナルのものは無理
・◯render(:new) && return
◯render :new and return
×render :new && return
・パラメーターを元にユーザーを取得するとか、そのユーザーを検証するとか、複数のアクションの冒頭で共通して行う処理は、privateにメソッドを作って、before_action
に設定すると良い
→特にget_user
とかは頻出
・絶対に成功するsaveはsave!
と書き(失敗時に例外が発生し処理が中断)、それ以外はsave
の戻り値で処理を分岐させる。
・エラーログに日本語を書くと文字化けしがちだから、英語で書くのが無難
・.to_s(:delimited)
で、3桁以上の数値にカンマをつけることができる
・とりあえず各ファイルの冒頭に# frozen_string_literal: true
を書き込んだ方が良いっぽい。文字列の破壊的変更をしたいときはhogehoge.dup
のように.dup
をつけると良い。
Ruby2.3で導入されたfrozen_string_literalマジックコメントでImmutable Stringを実現する
・Bundlerなしでgemを使う場合、必要な場面で毎回require
しないといけない。Bundlerを使ってgemを使うとrequire
を明示する必要がなくなる
・Gemfile内のgemにrequire: false
を追加すると、自動的にrequireされなくなる。
→テスト環境でしか使わないgemにrequire: falseが指定されることが多い。
→group test
内に書けば事足りるかも
・redirect_to
の引数は◯◯_path
だけじゃなくredirect_to '/user/show'
みたいな書き方もできる
・日時のフォーマットは.strftime
を使う
Time.zone.now.strftime('%Y年%m月%d日') #=>2020年02月04日
Time.zone.now.strftime('%Y年%-m月%-d日') #=>2020年2月4日
・redirect_to
とreturn
を1行で書きたい時には、redirect_to(hoge_path) && return
のように、引数をカッコで囲むと不具合が起きづらい
・railsでは(読むのが難しくなるとしても)できるだけ短い記述が好まれる
・before_save
系には以下の種類がある。
after_initialize (1)
before_validation (2)
after_validation (3)
before_save (4)
before_create (5)
after_create (6)
after_save (7)
after_commit (8)
Does before_save run after validations?
・User.new
とUser.build
は同じ。慣習的に、モデルの関連付けを行なっている場合などにはbuild
が使われる。(user.tasks.build
など)
・skip_before_action
ってのがあるのか!
・.blank?
は.nil?
と.empty?
の合体版。nilにempty?
を使うとエラーが発生するので、.blank?
の方が使いやすい印象。
・hoge: true
は:hoge
って書ける?
・boolean型のcompletedという属性があった時、自動的にcompleted?
というメソッドが使えるようになる?
・外部サーバーが落ちた時のリスクを減らすため、font-awesomeなどはできるだけcdnを使わないようにした方が良い。
・scopeはすごく便利そうだからどんどん使っていこう
Railsのモデルのscopeを理解しよう
・viewで使う関数で、特定のモデルとの関連が深いものはhelper
ではなくdecorator
を使う。
Decoratorの役割とDraperについて
・each
をmap
やinject
で置き換える
・truncate(文字数)
で文字列を省略して表示できる
pry(main)> 'あいうえおかきくけこ'.truncate(6)
=> "あいう..."
・外部サイトからのPOSTを許可したい時、コントローラーにprotect_from_forgery :except => [:action_name]
と書くと、そのコントローラーではCSRF対策をオフにすることができる。
・N+1
問題はincludes
を使って回避
#@comments = Comment.where(contact_id: params[:id])
@comments = Comment.where(contact_id: params[:id]).includes(:user)
<% @comments.each do |comment| %>
<li><%= comment.content %>:<%= comment.user.name %></li>
<% end %>
・文字列から特定の値を省きたい時はhogestring.gsub(/不要な文字列/, '')
・先頭2文字以外を「※」に変える
'1234567890'.gsub(/([0-9]{2})([0-9]+)/, '※※\2')
・**hash
でハッシュを展開できる
<%= link_to "csv出力", hoge_path(format: :csv, **take_params) %>
def take_params
{
from: params[:from],
to: params[:to]
}
end
・バリデーションエラーになったinput要素はdiv.field_with_errors
で囲まれる。radioボタン等のスタイルをカスタマイズしている場合、スタイルが崩れるので注意。
https://yukimasablog.com/rails-field-with-errors
・Railsでformから受け取ったparamsの型は「ActionController::Parameters」だから、このままだとループで回して必要なデータだけ取り出す、という処理はできない。params.to_unsafe_h でハッシュに変換すると良い。
https://qiita.com/kanna/items/171118e479c2dc76bb7c
ハマったところ
・gemparanoia
を利用中、application_record.rb
にacts_as_paranoid
と記述してしまい、論理削除を必要としないテーブルで
UnknownAttributeError: unknown attribute 'deleted_at' for Bill.
と怒られまくってしまった。
・gemを追加したあとは、サーバーを再起動しないと謎のエラーが起こりがち。
・管理者用の名前空間に作ったヘルパーメソッドhelper/admin/sessions_helper.rb
の冒頭にmodule Admin::SessionsHelper
ではなくmodule SessionsHelper
と書いてしまい、ヘルパーメソッドが無いと怒られた。
・2つのヘルパーファイル(helper/
以下]とhelper/admin/
以下)に同名のヘルパー関数を作ってしまい、後者を参照したいのに前者が参照されてしまった。
→viewから呼び出す時は、名前空間とか関係なく全部の関数が読み込まれる!
・データベースのカラム名にtype
を使った
→予約語だから普通に使うとエラーになる
・ハッシュの取り出しは@params.nameではなく@params['name']
・form_with
で名前空間admin
にあるコントローラーのアクションにデータを送りたい場合<%= form_with(model: [ :admin, @image ]) do |f| %>
のように書く
・ルーティングのPrefixが重複していて、formのactionがおかしくなっていた
・application.scss
で*= require_tree .
と記述すると、パーシャルまで個別に読み込んでしまい、undefined variableのエラーが発生する。
・DBを作ったブランチをマージせずに削除したら、There is 1 other session using the database.
というエラーが表示され、rails db:migrate:reset
が出来なくなった。
→データベースクライアント(Table Plus)を再起動したら解決。
・application_controllerにprotect_from_forgery
が書き込まれておらず、フォーム送信時にActionController::InvalidAuthenticityToken
のエラーが発生した
→Rails6からはデフォルトで書き込まれなくなった?
・違う名前空間の同名ファイルをいじっていた
・<%= form_with model: @hoge url: hoges_path, local: true do |f| %>
でフォームを作ったのに、@hoge
と関係無い情報(ファイル)送信して、params[:file]
で受け取ろうとしていた
・CSVを扱う時にCSV.foreach(file)
だとうまく行くときと行かない時がある。CSV.foreach(file.path)
にしたら解決した。
・minimagick
画像のリサイズをしていた時、resize_to_fit: [400, 400]
を指定しても画像が正方形にならず、minimagick自体が動作していないと思って時間を使った。
→指定したサイズに強制的に変更するオプションはresize_to_fill: [400, 400]
だった
・turbolinksをOFFにしたらlocal: true
をつけ忘れたフォームが動かなくなった。
・HerokuのPostgresで、ひらがなの並び替えがうまく行かなかった
PostgreSQLで正しく文字列ソート出来ない時の解決方法←で解決
・["hoge", nil, nil, "fuga"].split
を実行したら[["hoge"], [], ["fuga"]]
とカラムが3つに減ってしまった。
→split(',')
のように引数をとって解決
・メソッド名にsend
を使ったら、予約語だったらしくArgumentError: wrong number of arguments (given 0, expected 1)
が消えなかった
・繰り返し処理で配列にインスタンスを追加して、最終的にその配列を返す関数を作った時、処理の最後に配列名を書かなかったら、配列の中身がインスタンスじゃなくてハッシュっぽくなってて、取り出したデータに対してsave
メソッドが使えなかった。
・modelのメソッド内でredirect_to
は使えない
・アカウント有効化メール内のリンクのparamsにメールアドレスを仕込んだ時,+
が半角スペースになってしまった。
→解決策1:メールアドレスをパラメーターに持たせず、トークンだけで認証する
→解決策2:リンクのメールアドレス部分をCGI.escape()
でエスケープする。エスケープ解除はrailsが勝手にやってくれる
→解決策3:params[:email].gsub(' ', '+')
で半角スペースを+に置き換える
→リンクをhogehoge_url
の形で書けば、CGI.escapeを書かなくても自動でエスケープしてくれる
・ルーティングが見つからなかった時のリダイレクト用のルーティングの下に他のルーティングを書いても、使えなかった。
→ルーティングは上から評価される
・wicked pdf利用時、本番環境でのみThe asset "pdf.css" is not present in the asset pipeline.):
というエラーが表示され上手く動かなかった。
→CSSは全部HTML内に直書きしていたので、CSS読み込みの記述自体を削除して対応。
・DBの構造(ユニークキーなど)を変えた後、本番環境でユーザー情報の更新ができなくなった。
→本番環境のデータで、ユニークじゃないものがあったから。
・joinを使った複雑な検索を行った後の要素の集合をcount
メソッドでカウントしようとしたらエラーが出た
→代わりにsize
やlength
を使ったら解決した。理由はよくわからないままだけど、単純に数を数えたいだけの時はcount
を使う必要は無いみたい。countメソッドは、引数にブロックを渡したい時に使う。
Rubyにおけるsize, length, countの違いについて
・すでにnullのデータが入ってるカラムにdefault :null
を追加しようとして失敗した
・sorcery使用時、initializerの中のRails.application.config.sorcery.submodules = []
を誤って消してしまったら、モデル内のメソッドを一切呼び出せなくなった
・フォームの送信ボタンのdisable属性をゴニョゴニョする処理をjsで書いていたら、capybaraでclick_on '送信'
でクリックできなくなった。
→find('#submit').click
で解決。いろんな書き方がある。
・Rubyのmergeメソッドを使って、オブジェクトを結合することができる
user_params.merge(group_id: params[:user][:groups])
みたいに使える