2
3

More than 3 years have passed since last update.

Ruby on Railsに関するメモ

Last updated at Posted at 2020-01-31

高速に開発するために

・とりあえず、適切なブランチに移動し、コントローラーと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_todata: {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はnoticealertだけ。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_toreturnを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.newUser.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について

eachmapinjectで置き換える

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でハッシュを展開できる

view
<%= link_to "csv出力", hoge_path(format: :csv, **take_params) %>
helper
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.rbacts_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メソッドでカウントしようとしたらエラーが出た
→代わりにsizelengthを使ったら解決した。理由はよくわからないままだけど、単純に数を数えたいだけの時は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])みたいに使える

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3