Rails開発者が犯した5つのよくある間違い



私はかなり長い間Railsを扱ってきましたが、この間に多くのRailsアプリケーションを見てきました。また、多くの悪いRubyコードを読み書きしました。 そして、ほとんどすべてのアプリケーションで私が観察した最も一般的な5つのエラーを以下に示します。



1.制限なしの移行



データモデルは、アプリケーションの中心です。 回路の制限がなければ、コードのバグにより、データベースの単一フィールドではなく完全に信頼できるようになるまで、データはゆっくりと破壊されます。 連絡先モデルの図は次のとおりです。



create_table "contacts" do |t| t.integer "user_id" t.string "name" t.string "phone" t.string "email" end
      
      





ここに何が欠けていますか? 最も可能性の高い連絡先は、ユーザー( User )に属し( belongs_to )、少なくとも名前が必要です-これにはデータベースの制限を使用してください。 「 :null => false 」を追加することにより、検証コードにバグがある場合でも、モデル自体の整合性を常に確認できます。データベース自体ではこれらの制限に違反するモデルを保存できないためです。



 create_table "contacts" do |t| t.integer "user_id", :null => false t.string "name", :null => false t.string "phone" t.string "email" end
      
      





ボーナスのヒント : " :limit => N "を使用して、文字列フィールドの適切なサイズを示します。 デフォルトでは、行の長さは255文字に設定されています。おそらく、「 電話 」フィールドはこのサイズをまったく必要としませんが、それは論理的ですか?



2.オブジェクト指向プログラミング



ほとんどのRails開発者は、オブジェクト指向のRubyコードを作成しません。 モデルとコントローラーを目的のフォルダーに展開して、MVC指向のコードを記述します。 クラスメソッドを持つヘルパーモジュールを「lib」フォルダーに追加するものもありますが、それ以上は追加しません。 開発者が気付くまでに2〜3年かかります。「Railsは単なるRubyです。 単純なオブジェクトを作成し、フレームワークを使用して、彼が指定したとおりではなく、好きなように構成できます。



ボーナスヒント :使用するサードパーティサービスのファサードを作成します。 テスト中にサードパーティのサービスをプルしないように、テストで使用するファサードモックを作成します。



3.ヘルパーでのHTML連結



ヘルパーメソッドを作成する場合(よくやった!)、少なくともあなたはテンプレートをきれいに保とうとしています。 しかし、多くの場合、開発者はヘルパー内でタグを作成する基本を知らず、接着された行のハッシュにつながります。



 str = "<li class='vehicle_list'> " str += link_to("#{vehicle.title.upcase} Sale", show_all_styles_path(vehicle.id, vehicle.url_title)) str += " </li>" str.html_safe
      
      





すず! これはく、簡単にXSSの脆弱性につながります。 content_tagはあなたの友達です!



 content_tag :li, :class => 'vehicle_list' do link_to("#{vehicle.title.upcase} Sale", show_all_styles_path(vehicle.id, vehicle.url_title)) end
      
      





おまけのヒント :ブロックを引数として取るヘルパーの使用を開始します。 ネストされたHTMLは、ネストされたブロックを生成する必要がある場合に最適です。



4.巨大なクエリはすべてをメモリにロードします



データ内の何かを修正する必要があり、ループ内でそれらをすべて調べて修正しますか?



 User.has_purchased(true).each do |customer| customer.grant_role(:customer) end
      
      





商用サイトと100万人のユーザーがいると想像してください。 Userクラスの各オブジェクトがメモリで500バイトを占めるようにします。 コードは500 MBのメモリを消費します。 より良いオプション:



 User.has_purchased(true).find_each do |customer| customer.grant_role(:customer) end
      
      





find_eachfind_in_batchesメソッドを内部的に使用して、 一度に 1000レコードを選択し、メモリ消費を大幅に削減します。



ボーナスヒントupdate_allまたはbare SQLを使用して、バルクデータ更新を実行します。 SQLの学習には時間がかかりますが、得られるメリットは非常に大きくなります。最大100倍のパフォーマンスの向上です。



5.コードレビュー



私はあなたがGitHubを使用していると仮定し、またプールリクエストを使用していないと仮定します。 1日か2日かけて新しい機能を実装する場合は、別のブランチでそれを実行し、プールリクエストを使用します。 あなたのチームはあなたのコードをチェックし、改善できるものを提案し、あなたが見失うかもしれないいくつかのポイントをあなたに示すことができます。 これにより、コードの品質が向上することを保証します。



ボーナスヒント :成功したテストなしでプールリクエストを受け入れないでください。 テストは、アプリケーションを安定させ、安らかな睡眠を保つために非常に貴重です。






ボーナス:元の記事に対する有益なコメント


find_eachfind_in_batchesは大規模な選択に適していますが、アプリケーションメモリをデータベースのプロセッササイクルに変更していることに注意してください。



1'000'000レコードを返すクエリを作成するとします。



 SELECT * FROM users WHERE unindexed_field = true;
      
      





User.all.eachを実行すると、データベースは1つの巨大なクエリを作成し、結果全体を一度に計算します。 User.where(...)。Find_each(:batch_size => 100)を実行すると、データベースは同じクエリを1'000'000 / 100 = 10'000回行う必要があります。 また、MySQLを使用する場合は、毎回結果を再カウントします。 つまり レコード100-200の場合、彼は200-300-最初の300レコード、そして300-400-最初の400レコードなど、999900-1000000までの最初の200レコードを計算します。



したがって、選択範囲が大きい場合は、もちろんfind_eachまたはfind_in_batchesを使用することをお勧めしますが、これも問題を引き起こす可能性があることに留意してください。



この問題を解決するための一般的な「ハック」は次のとおりです。



 ids = User.where(...).select(:id).all ids.in_groups_of(100) do |id_group| # ... end
      
      






All Articles