Ruby / RoR開発者の10のよくある間違いとそれらを避けるためのヒントを紹介します。 コードのデバッグ時間の短縮に役立つことを願っています。
1.二重否定と困難な条件。
if !user.nil? # ... end unless user.blank? # ... end unless user.active? || address.confirmed? # ... end
ダブルネガは読みにくいです。 条件を解析するために数秒を費やすたびに。 Rails APIを使用して、user.presentを記述しますか? 代わりに!user.blank?。
また、特に複数の条件で正当化されない限り 、私はめったに見つけません。 この条件が満たされる場合、どのくらい早く実現しますか?
unless user.active? || address.confirmed? ... end
2. 保存の代わりに保存を使用してください! 戻り値をチェックせずに。
user = User.new user.name = "John" user.save
このコードの問題は何ですか? 保存エラーが発生しても気づかないでしょう。 ログにはトレースが1つも残っていないので、「データベースにユーザーがいないのはなぜか」ということを理解しようとして多くの時間を費やすことになります。
データが常に正しく、レコードを保存する必要があることが確実な場合は、 bangメソッド(save!、create!など)を使用します。 戻り値を確認する場合にのみ保存を使用します。
if user.save ... else ... end
3.必要なく自己を使用します。
class User attr_accessor :first_name attr_accessor :last_name def display_name "#{self.first_name} #{self.last_name}" end end
self.first_nameの場合、first_nameを書き込むだけで、結果は変わりません。 しかし、これはむしろスタイルの問題であり、否定的な結果をもたらしません。 ただし、値を割り当てるときはselfを使用する必要があることに注意してください。
self.first_name = "John"
4. N + 1リクエストの問題。
posts = Post.limit(10) posts.each do |post| do_smth post.user end
このコードを実行するときにログを見ると、11のデータベースクエリが実行されていることがわかります。1つは投稿の選択用、もう1つは各ユーザー用です。 Railsはあなたの欲望を予測することはできず、10人のユーザーを一度にアンロードするリクエストを行うことはできません(投稿がある場合でも)。 Railsを正しい方向に向けるために、 includesメソッドを使用できます(詳細はこちら )。
5. 3つの値を持つブールフィールド。
ブール値フィールドは、trueまたはfalseの2つの値しか持つことができないと想定されていますか? nilはどうですか? 移行でデフォルト値を指定してnull:falseオプションを追加するのを忘れた場合は、3つのブール値(true、false、nil)を処理する必要があります。 その結果、同様のコードがあります。
# , if post.published.nil? # ... end # if post.published # ... end # unless post.published # ... end
3つの異なる値を処理する必要がある場合は、テキストボックスを使用します。
6.削除後に失われたレコード。
簡単な例を考えてみましょう。
class User < ActiveRecord::Base has_many :posts end class Post < ActiveRecord::Base belongs_to :user validates_presence_of :user end
ユーザーを削除すると、そのユーザーに関連付けられた投稿は正しくなくなります(ほとんどの場合、アプリケーションでエラーが発生します)。 この場合、関連オブジェクトの削除を処理する必要があります。
class User < ActiveRecord::Base has_many :posts, dependent: :delete end
7.移行でのアプリケーションコードの使用。
次のモデルがあるとします:
class User < ActiveRecord::Base ACTIVE = "after_registration" end
それにポイントフィールドを追加します。 これを行うには、移行を作成します。 また、既存のユーザーのポイントフィールドの値を10に設定する必要があります。このために、移行を記述します。
User.where(status: User::ACTIVE).update_all(points: 10)
移行を開始します。 -うまくいきました。既存のユーザーには10ポイントがあります。 時間が経ち、コードが変更され、User :: ACTIVE定数を削除することにしました。 これ以降、移行は機能せず、移行を最初から開始することはできません( 初期化されていない定数User :: ACTIVEのエラーが表示されます )。
ヒント:移行内でアプリケーションコードを使用しないでください。 たとえば、一時的なRakeタスクを使用して、既存のデータを変更します。
翻訳者注:
私の意見では、一時的な移行を使用して値を変更する方がはるかに便利です。 特に本番環境への変更を展開する場合:rakeの実行を忘れる可能性は決してゼロではありません。Capistranoが移行を開始します。
また、リリース後に一時的な移行をクリーンアップできます。
8.遍在者はを置きます。
デバッグ後の残りは、テスト実行中にログと出力を詰まらせます。 Rails.logger.debugを使用します。これにより、選択したレベルに応じてログをフィルタリングできます。
メモ翻訳者:
また、デバッガーの使用方法を学習します。 この場合、commitする前にbinding.pryを削除することを忘れないでください。
9. 地図を忘れる。
私はしばしば同様のコードを見ます:
users = [] posts.each do |post| users << post.user end
これは、 mapを簡潔かつ慣用的に使用する必要がある場合に当てはまります。
users = posts.map do |post| post.user end # (. ) users = posts.map(&:user)
10. Hash#fetchを使用しないでください。
name = params[:user][:name]
ここで何が間違っていますか? ハッシュにユーザーキーがない場合、このコードは例外( NoMethodError:undefined method `[] 'for nil:NilClass )をスローします。 キーがハッシュであると予想される場合は、ハッシュ#フェッチを使用します。
name = params.fetch(:user)[:name]
次に、より意味のある例外が表示されます。
KeyError: key not found: :user
結論の代わりに。
好きな間違いは何ですか?