├── CONTRIBUTING.md ├── README-jaJA.md └── README.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | * [Fork](https://help.github.com/articles/fork-a-repo) the project on GitHub. 2 | * Make your feature addition or bug fix in a feature branch. (Include a description of your changes) 3 | * Push your feature branch to GitHub. 4 | * Send a [Pull Request](https://help.github.com/articles/using-pull-requests). -------------------------------------------------------------------------------- /README-jaJA.md: -------------------------------------------------------------------------------- 1 | # 序 2 | 3 | > “ロールモデルが重要なのだ。”
4 | > -- アレックス・マーフィー巡査 / 映画『ロボコップ』の登場人物 5 | 6 | このガイドの目的は、Ruby on Rails 4 開発における コーディングスタイルのベストプラクティスを提供することです。すでに有志によって作成された[Ruby coding style guide](https://github.com/bbatsov/ruby-style-guide)の補足資料にあたります。 7 | 8 | 記載内容の一部は Rails 4.0 以上のみを対象としています。 9 | 10 | PDF形式やHTML形式のコピーは[Transmuter](https://github.com/TechnoGate/transmuter)を使って作成できます。 11 | 12 | 13 | 以下の言語の翻訳が利用可能です: 14 | 15 | * [中国語(簡体)](https://github.com/JuanitoFatas/rails-style-guide/blob/master/README-zhCN.md) 16 | * [中国語(繁体)](https://github.com/JuanitoFatas/rails-style-guide/blob/master/README-zhTW.md) 17 | * [日本語](hhttps://github.com/satour/rails-style-guide/blob/master/README-jaJA.md) 18 | * [ロシア語](https://github.com/arbox/rails-style-guide/blob/master/README-ruRU.md) 19 | * [トルコ語](https://github.com/tolgaavci/rails-style-guide/blob/master/README-trTR.md) 20 | 21 | # The Rails Style Guide 22 | 23 | このガイドは、Rails開発の実務におけるコーディングスタイルのベストプラクティスを目指したものです。開発における理想論は多くありますが、このガイドはあくまで実務での利用に役立つことを目的としています。このガイドの内容は絶対ではありませんが、非常に多くのRails開発者のフィードバックや資料を基にして書かれたものです。ここで改めて、彼らへ多大な感謝を示します。 24 | 25 | ## 目次 26 | 27 | * [Configuration](#configuration) 28 | * [Routing](#routing) 29 | * [Controllers](#controllers) 30 | * [Models](#models) 31 | * [ActiveRecord](#activerecord) 32 | * [ActiveRecord Queries](#activerecord-queries) 33 | * [Migrations](#migrations) 34 | * [Views](#views) 35 | * [Internationalization](#internationalization) 36 | * [Assets](#assets) 37 | * [Mailers](#mailers) 38 | * [Time](#time) 39 | * [Bundler](#bundler) 40 | * [Flawed Gems](#flawed-gems) 41 | * [Managing processes](#managing-processes) 42 | 43 | ## Configuration 44 | 45 | * 46 | アプリケーション起動時の処理をカスタマイズしたい場合は、 `config/initializers` 配下にその処理を記述したコードを配置しましょう。`config/initializers` 配下のコードはアプリケーション起動時に実行されます。 47 | [[link](#config-initializers)] 48 | 49 | * 50 | gem の初期化に必要なコードは、gem 毎に作成しましょう。また、そのファイルの名前は gem の名前と同じにしましょう。例えば、 `carrierwave.rb`、 `active_admin.rb`などです。 51 | [[link](#gem-initializers)] 52 | 53 | * 54 | Railsには3つの環境(development、test、 production)がありますが、環境毎に適切な設定をしましょう。 55 | ( `config/environments/`配下にそれぞれの環境に対応した設定ファイルが配置してあります。) 56 | [[link](#dev-test-prod-configs)] 57 | 58 | * もしプリコンパイルを行う場合は、追加するアセット名を明記しましょう。: 59 | 60 | ```Ruby 61 | # config/environments/production.rb 62 | # Precompile additional assets (application.js, application.css, 63 | #and all non-JS/CSS are already added) 64 | config.assets.precompile += %w( rails_admin/rails_admin.css rails_admin/rails_admin.js ) 65 | ``` 66 | 67 | * 68 | 設定をすべての環境に適用したい場合は、 `config/application.rb` に記述しましょう. 69 | [[link](#app-config)] 70 | 71 | * 72 | `production`環境と同環境の `staging` 環境を作成しておきましょう。 73 | [[link](#staging-like-prod)] 74 | 75 | ## Routing 76 | 77 | * 78 | もしRESTfulなresourceにアクションを追加する場合(そのようなアクションが本当に必要かはわかりませんが)、 `member` と `collection` を利用しましょう。 79 | [[link](#member-collection-routes)] 80 | 81 | ```Ruby 82 | # 悪い例 83 | get 'subscriptions/:id/unsubscribe' 84 | resources :subscriptions 85 | 86 | # 良い例 87 | resources :subscriptions do 88 | get 'unsubscribe', on: :member 89 | end 90 | 91 | # 悪い例 92 | get 'photos/search' 93 | resources :photos 94 | 95 | # 良い例 96 | resources :photos do 97 | get 'search', on: :collection 98 | end 99 | ``` 100 | 101 | * 102 | 複数の`member/collection`を定義しなければいけない場合は、ブロック構文を利用しましょう。[[link](#many-member-collection-routes)] 103 | 104 | 105 | ```Ruby 106 | resources :subscriptions do 107 | member do 108 | get 'unsubscribe' 109 | # more routes 110 | end 111 | end 112 | 113 | resources :photos do 114 | collection do 115 | get 'search' 116 | # more routes 117 | end 118 | end 119 | ``` 120 | 121 | * 122 | ActiveRecordのモデル間の関連を表現するには、入れ子型でルートを定義すると分かりやすいでしょう。[[link](#nested-routes)] 123 | 124 | ```Ruby 125 | class Post < ActiveRecord::Base 126 | has_many :comments 127 | end 128 | 129 | class Comments < ActiveRecord::Base 130 | belongs_to :post 131 | end 132 | 133 | # routes.rb 134 | resources :posts do 135 | resources :comments 136 | end 137 | ``` 138 | 139 | * 140 | 関連する アクション・ルートをまとめるには `namespace`を利用しましょう。[[link](#namespaced-routes)] 141 | 142 | ```Ruby 143 | namespace :admin do 144 | # Directs /admin/products/* to Admin::ProductsController 145 | # (app/controllers/admin/products_controller.rb) 146 | resources :products 147 | end 148 | ``` 149 | 150 | * 151 | Railsに昔あった古いルーティング記法は絶対に利用しないようにしましょう。この記法を利用した場合、すべてのアクションへのすべてのGETリクエストを許可してしまいます。[[link](#no-wild-routes)] 152 | 153 | ```Ruby 154 | # 非常に悪い例 155 | match ':controller(/:action(/:id(.:format)))' 156 | ``` 157 | 158 | * 159 | `match` を利用しないようにしましょう。もし利用する必要がある場合は、アクション毎に `:via` オプションで`[:get, :post, :patch, :put, :delete]`を指定しましょう。 [[link](#no-match-routes)] 160 | 161 | ## Controllers 162 | 163 | * 164 | ビジネスロジックは controller でなく model に書きましょう。controller の役割は、view層にデータを渡すこと、またはview層からデータを受け取ることのいずれかのみです。それ以外のコードは controller に記述しないようにしましょう。[[link](#skinny-controllers)] 165 | 166 | * 167 | (理想論ですが)すべての controller は find と new 以外のメソッドはひとつ程度に留められるようにしましょう。[[link](#one-method)] 168 | 169 | * 170 | controller と view の間でやりとりするインスタンス変数は2つまでに留めておきましょう。[[link](#shared-instance-variables)] 171 | 172 | ## Models 173 | 174 | * 175 | ActiveRecord を継承しないモデルも導入しましょう。 176 | [[link](#model-classes)] 177 | 178 | * 179 | モデルの名前は、意味が通じてなおかつ短いものにしましょう。その際には省略語は利用しないようにしましょう。 180 | [[link](#meaningful-model-names)] 181 | 182 | * 183 | ActiveRecordのような振る舞い(validationなど)が必要なモデルには、[ActiveAttr](https://github.com/cgriego/active_attr) 184 | のような gem を使いましょう. 185 | [[link](#activeattr-gem)] 186 | 187 | ```Ruby 188 | class Message 189 | include ActiveAttr::Model 190 | 191 | attribute :name 192 | attribute :email 193 | attribute :content 194 | attribute :priority 195 | 196 | attr_accessible :name, :email, :content 197 | 198 | validates :name, presence: true 199 | validates :email, format: { with: /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i } 200 | validates :content, length: { maximum: 500 } 201 | end 202 | ``` 203 | 204 | 詳細な例は[RailsCast on the subject](http://railscasts.com/episodes/326-activeattr)に譲ります。 205 | 206 | ### ActiveRecord 207 | 208 | * 209 | データベースの操作を自由に出来ない等、特別な理由がない限り、ActiveRecord の初期値(テーブル名、主キー等)を変更しないようにしましょう。 210 | [[link](#keep-ar-defaults)] 211 | 212 | ```Ruby 213 | # 悪い例 214 | class Transaction < ActiveRecord::Base 215 | self.table_name = 'order' 216 | ... 217 | end 218 | ``` 219 | 220 | * 221 | `has_many`や`validates`などはクラス定義の最初の方に記述しましょう。(satour注:本文と例が一致していません@原文) 222 | [[link](#macro-style-methods)] 223 | 224 | ```Ruby 225 | class User < ActiveRecord::Base 226 | # 一番上にデフォルト・スコープを記述する。 227 | default_scope { where(active: true) } 228 | 229 | # 定数を記述する。 230 | COLORS = %w(red green blue) 231 | 232 | # attr関連のマクロを記述する。 233 | attr_accessor :formatted_date_of_birth 234 | 235 | attr_accessible :login, :first_name, :last_name, :email, :password 236 | 237 | # アソシエーションに関するマクロを記述する。 238 | belongs_to :country 239 | 240 | has_many :authentications, dependent: :destroy 241 | 242 | # ヴァリデーションに関するマクロを記述する。 243 | validates :email, presence: true 244 | validates :username, presence: true 245 | validates :username, uniqueness: { case_sensitive: false } 246 | validates :username, format: { with: /\A[A-Za-z][A-Za-z0-9._-]{2,19}\z/ } 247 | validates :password, format: { with: /\A\S{8,128}\z/, allow_nil: true} 248 | 249 | # コールバックを記述する。 250 | before_save :cook 251 | before_save :update_username_lower 252 | 253 | # 上記以外のマクロがある場合、コールバックの下に続けて記述する。 254 | 255 | ... 256 | end 257 | ``` 258 | 259 | * 260 | なるべく`has_and_belongs_to_many`より`has_many :through`を利用しましょう。`has_many :through` を使うと model を join する際に属性やヴァリデーションを利用することが出来ます。 261 | [[link](#has-many-through)] 262 | 263 | ```Ruby 264 | # あまり良くない例 265 | class User < ActiveRecord::Base 266 | has_and_belongs_to_many :groups 267 | end 268 | 269 | class Group < ActiveRecord::Base 270 | has_and_belongs_to_many :users 271 | end 272 | 273 | # 良い例 274 | class User < ActiveRecord::Base 275 | has_many :memberships 276 | has_many :groups, through: :memberships 277 | end 278 | 279 | class Membership < ActiveRecord::Base 280 | belongs_to :user 281 | belongs_to :group 282 | end 283 | 284 | class Group < ActiveRecord::Base 285 | has_many :memberships 286 | has_many :users, through: :memberships 287 | end 288 | ``` 289 | 290 | * 291 | なるべく`read_attribute(:attribute)`より`self[:attribute]`を利用しましょう。 292 | [[link](#read-attribute)] 293 | 294 | ```Ruby 295 | # 悪い例 296 | def amount 297 | read_attribute(:amount) * 100 298 | end 299 | 300 | # 良い例 301 | def amount 302 | self[:amount] * 100 303 | end 304 | ``` 305 | 306 | * 307 | なるべく`write_attribute(:attribute, value)`より`self[:attribute] = value`を利用しましょう。 308 | [[link](#write-attribute)] 309 | 310 | ```Ruby 311 | # 悪い例 312 | def amount 313 | write_attribute(:amount, 100) 314 | end 315 | 316 | # 良い例 317 | def amount 318 | self[:amount] = 100 319 | end 320 | ``` 321 | 322 | * 323 | ["sexy" 324 | validations](http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/) を利用しましょう。 325 | [[link](#sexy-validations)] 326 | 327 | ```Ruby 328 | # 悪い例 329 | validates_presence_of :email 330 | 331 | # 良い例 332 | validates :email, presence: true 333 | ``` 334 | 335 | * 336 | 独自のヴァリデーションが2回以上呼び出される場合、もしくは独自のヴァリデーションが正規表現を含む場合は、ファイルとして切り出しましょう。 337 | [[link](#custom-validator-file)] 338 | 339 | ```Ruby 340 | # 悪い例 341 | class Person 342 | validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i } 343 | end 344 | 345 | # 良い例 346 | class EmailValidator < ActiveModel::EachValidator 347 | def validate_each(record, attribute, value) 348 | record.errors[attribute] << (options[:message] || 'is not a valid email') unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i 349 | end 350 | end 351 | 352 | class Person 353 | validates :email, email: true 354 | end 355 | ``` 356 | 357 | * 358 | 独自のヴァリデーション・ファイルは`app/validators`を作成し、その配下に配置しましょう。 359 | [[link](#app-validators)] 360 | 361 | * 362 | 独自のヴァリデーションを使って複数のアプリケーションをメンテナンスしている場合、もしくはそのヴァリデーションが汎用的な内容である場合、gem 化することを検討しましょう。 363 | [[link](#custom-validators-gem)] 364 | 365 | * 366 | 名前付きスコープを取り入れましょう。 367 | [[link](#named-scopes)] 368 | 369 | ```Ruby 370 | class User < ActiveRecord::Base 371 | scope :active, -> { where(active: true) } 372 | scope :inactive, -> { where(active: false) } 373 | 374 | scope :with_orders, -> { joins(:orders).select('distinct(users.id)') } 375 | end 376 | ``` 377 | 378 | * 379 | 名前付きスコープがラムダ式で定義されており、かつ引数が複雑になってきた際には、スコープ名と同名の`ActiveRecord::Relation`オブジェクトを返すクラスメソッドを作成することが望ましいです。そうすることで記述を簡潔にすることができます。 380 | [[link](#named-scope-class)] 381 | 382 | ```Ruby 383 | class User < ActiveRecord::Base 384 | def self.with_orders 385 | joins(:orders).select('distinct(users.id)') 386 | end 387 | end 388 | ``` 389 | 390 | * 391 | [`update_attribute`](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute) は`update_attributes`と異なり、モデルのヴァリデーション実行をスキップするので、利用する際は気をつけましょう。 392 | [[link](#beware-update-attribute)] 393 | 394 | * 395 | ユーザー・フレンドリーな URL を用意しましょう。下記に例を示します。 396 | [[link](#user-friendly-urls)] 397 | 398 | * ここでは、`to_param` を上書きします。このメソッドはRailsによるURL作成に使用されます。デフォルトの実装ではレコードの`id`を`String`型で返します。 399 | 400 | ```Ruby 401 | class Person 402 | def to_param 403 | "#{id} #{name}".parameterize 404 | end 405 | end 406 | ``` 407 | 408 | * `to_param`の返り値をURL-friendlyな値にするために, 文字列を`parameterize` します。`parameterize`ではオブジェクトをActiveRecordの`find`メソッドで検索できるようにする為、`id`を文字列の一番先頭に置きます。 409 | 410 | * `friendly_id`という gem を利用しましょう。`id`のかわりに model の他の属性を使って、読みやすいURLを生成することが出来ます。 411 | 412 | ```Ruby 413 | class Person 414 | extend FriendlyId 415 | friendly_id :name, use: :slugged 416 | end 417 | ``` 418 | 419 | より詳細な内容は [gem documentation](https://github.com/norman/friendly_id) に譲ります。 420 | 421 | * 422 | ActiveRecordのオブジェクトに対して繰り返し処理を行う場合は、`find_each`を利用しましょう。(`all`などで)DBから取得したレコードセットを直接繰り返し処理させる場合、すべてのオブジェクトを即時にインスタンス化することが求められ、大量にメモリを消費します。`find_each`はインスタンス化を逐次処理にできるため、メモリ量の消費を抑制することが出来ます。 423 | [[link](#find-each)] 424 | 425 | 426 | ```Ruby 427 | # 悪い例 428 | Person.all.each do |person| 429 | person.do_awesome_stuff 430 | end 431 | 432 | Person.where('age > 21').each do |person| 433 | person.party_all_night! 434 | end 435 | 436 | # 良い例 437 | Person.find_each do |person| 438 | person.do_awesome_stuff 439 | end 440 | 441 | Person.where('age > 21').find_each do |person| 442 | person.party_all_night! 443 | end 444 | ``` 445 | 446 | * 447 | [Rails creates callbacks for dependent 448 | associations](https://github.com/rails/rails/issues/3458) により、 449 | `before_destroy`には`prepend: true`オプションを付けましょう。(satour注:リンク先の内容がタイトルから連想される内容と異なる。またリンク先のissueはcloseされている。) 450 | 451 | ```Ruby 452 | # 悪い例 (super_admin? が true でもrolesが自動的にdeleteされる。) 453 | has_many :roles, dependent: :destroy 454 | 455 | before_destroy :ensure_deletable 456 | 457 | def ensure_deletable 458 | fail "Cannot delete super admin." if super_admin? 459 | end 460 | 461 | # 良い例 462 | has_many :roles, dependent: :destroy 463 | 464 | before_destroy :ensure_deletable, prepend: true 465 | 466 | def ensure_deletable 467 | fail "Cannot delete super admin." if super_admin? 468 | end 469 | ``` 470 | 471 | ### ActiveRecord Queries 472 | 473 | * 474 | SQLインジェクション攻撃を防ぐため、クエリの文字列の中で式を展開するのはやめましょう。 475 | [[link](#avoid-interpolation)] 476 | 477 | ```Ruby 478 | # bad - paramがエスケープされず、SQLインジェクションの可能性が残る。 479 | Client.where("orders_count = #{params[:orders]}") 480 | 481 | # good - paramがエスケープされる 482 | Client.where('orders_count = ?', params[:orders]) 483 | ``` 484 | 485 | * 486 | クエリのなかで2つ以上のプレースホルダを使う場合は、 487 | 名前付きプレースホルダを利用しましょう。 488 | [[link](#named-placeholder)] 489 | 490 | ```Ruby 491 | # okish 492 | Client.where( 493 | 'created_at >= ? AND created_at <= ?', 494 | params[:start_date], params[:end_date] 495 | ) 496 | 497 | # good 498 | Client.where( 499 | 'created_at >= :start_date AND created_at <= :end_date', 500 | start_date: params[:start_date], end_date: params[:end_date] 501 | ) 502 | ``` 503 | 504 | * 505 | idを指定してひとつのレコードを取得する場合は、`where`より`find`を使いましょう。 506 | [[link](#find)] 507 | 508 | ```Ruby 509 | # bad 510 | User.where(id: id).take 511 | 512 | # good 513 | User.find(id) 514 | ``` 515 | 516 | * 517 | 複数の属性を指定してひとつのレコードを取得する場合は、`where`より`find_by`を使いましょう。 518 | 519 | [[link](#find_by)] 520 | 521 | ```Ruby 522 | # bad 523 | User.where(first_name: 'Bruce', last_name: 'Wayne').first 524 | 525 | # good 526 | User.find_by(first_name: 'Bruce', last_name: 'Wayne')) 527 | ``` 528 | 529 | * 530 | 大量のレコードを処理しなければいけない場合は、`find_each`を使いましょう。 531 | [[link](#find_each)] 532 | 533 | ```Ruby 534 | # bad - すべてのレコードを一度に読み込む 535 | usersテーブルに数千行のレコードがあった場合、この書き方では非常に非効率になる。 536 | 537 | User.all.each do |user| 538 | NewsMailer.weekly(user).deliver_now 539 | end 540 | 541 | # good - バッチのなかでレコードが読み込まれる 542 | User.find_each do |user| 543 | NewsMailer.weekly(user).deliver_now 544 | end 545 | ``` 546 | 547 | * 548 | SQLのようにクエリを記述する場合、`where.not`を使った方がよいケースがあります。 549 | [[link](#where-not)] 550 | 551 | ```Ruby 552 | # bad 553 | User.where("id != ?", id) 554 | 555 | # good 556 | User.where.not(id: id) 557 | ``` 558 | 559 | ## Migrations 560 | 561 | * 562 | `schema.rb` (または `structure.sql`) は必ずバージョン管理しましょう。 563 | [[link](#schema-version)] 564 | 565 | * 566 | 最新のスキーマで空のデータベースを作る際には、`rake db:migrate`でなく`rake db:schema:load`を利用しましょう。 567 | [[link](#db-schema-load)] 568 | 569 | * 570 | フィールドの初期値の設定処理は、アプリケーションの中に記述せず、migration ファイルに記述しましょう。 571 | [[link](#default-migration-values)] 572 | 573 | ```Ruby 574 | # 悪い例 - アプリケーションでデフォルト値を設定している。 575 | def amount 576 | self[:amount] or 0 577 | end 578 | ``` 579 | 580 | 多くのRails開発者が、初期値の設定をRailsのアプリケーション層だけで行っています。しかし、そのやり方はデータの不整合やアプリケーションのバグを引き起こす可能性が高いです。また、重要なアプリケーションは、データベースを他のアプリケーションと共有している場合が多く、単体のRailsアプリケーションでデータ保全性を担保するのは不可能です。 581 | 582 | * 583 | 外部キー制約を設定しましょう。Railは4.2から外部キー制約をサポートしています。 584 | [[link](#foreign-key-constraints)] 585 | 586 | * 587 | スキーマを変更する(テーブルの追加、フィールドの追加など)migrationを書くときは、`up`や`down`でなく`change`を利用しましょう。 588 | [[link](#change-vs-up-down)] 589 | 590 | ```Ruby 591 | # 古い書き方(古いバージョンのRailsではこのような書き方しか出来ませんでした。) 592 | class AddNameToPeople < ActiveRecord::Migration 593 | def up 594 | add_column :people, :name, :string 595 | end 596 | 597 | def down 598 | remove_column :people, :name 599 | end 600 | end 601 | 602 | # こちらの方が好ましい 603 | class AddNameToPeople < ActiveRecord::Migration 604 | def change 605 | add_column :people, :name, :string 606 | end 607 | end 608 | ``` 609 | 610 | * 611 | migration でモデルを利用してはいけません。モデルの内容は更新されていくものであり、migration でモデルを引用していた場合、migrationの実行時に不具合を起こす可能性が高いです。 612 | [[link](#no-model-class-migrations)] 613 | 614 | ## Views 615 | 616 | * 617 | viewから直接、モデル層を呼び出さないようにしましょう。 618 | [[link](#no-direct-model-view)] 619 | 620 | * 621 | Viewでの表示のための複雑なフォーマット処理をviewのファイルに記述してはいけません。ヘルパーメソッドに書き出しましょう。 622 | [[link](#no-complex-view-formatting)] 623 | 624 | * 625 | 同じコードを複数箇所に書くのは非効率です。複数のviewで同じコードを書く場合は、部分テンプレートやレイアウトにまとめましょう。 626 | [[link](#partials)] 627 | 628 | ## Internationalization 629 | 630 | * 631 | 国際化(国や土地によって文字列を翻訳する)したい文字列は、すべて`config/locales`配下のlocaleファイル(辞書ファイル)で定義しましょう。 632 | [[link](#locale-texts)] 633 | 634 | * 635 | 国際化する場合、ActiveRecordのmodelのラベルには必ず対訳が必要です。各辞書ファイルで`activerecord` スコープを使って対訳を定義しましょう。 636 | [[link](#translated-labels)] 637 | 638 | ``` 639 | en: 640 | activerecord: 641 | models: 642 | user: Member 643 | attributes: 644 | user: 645 | name: 'Full name' 646 | ``` 647 | 648 | この場合、`User.model_name.human` は "Member" を返し、`User.human_attribute_name("name")` は "Full name" を返します。これらの対訳はviewでのラベル表示で使用されます。 649 | 650 | 651 | * 652 | ActiveRecord の model の対訳と view で使用するテキストは別々の辞書ファイルに定義しましょう。model の対訳は`model`ディレクトリを作成しその配下に辞書ファイルを作成しましょう。また view での用いる対訳は`views`ディレクトリを作成し、その配下に辞書ファイルを作成しましょう. 653 | [[link](#organize-locale-files)] 654 | 655 | * 辞書ファイルを格納したディレクトリが分散する場合、 `application.rb` で辞書ファイルを格納しているディレクトリを指定する必要があります。 656 | 657 | ```Ruby 658 | # config/application.rb 659 | config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')] 660 | ``` 661 | 662 | * 663 | データフォーマットや通貨表記など、どのlocaleでも共通して利用したい文字列は、`locales` 直下にファイルを作成しそこに定義しましょう。 664 | [[link](#shared-localization)] 665 | 666 | * 667 | 挙動が同じなら、利用するメソッドは名称が短い方が望ましいです。`I18n.translate`ではなく`I18n.t`を使いましょう。また、`I18n.localize`でなく、`I18n.l`を使いましょう。 668 | [[link](#short-i18n)] 669 | 670 | * 671 | View では、"lazy lookup" を利用しましょう。 672 | [[link](#lazy-lookup)] 673 | 674 | ``` 675 | en: 676 | users: 677 | show: 678 | title: 'User details page' 679 | ``` 680 | 681 | 辞書ファイルでこのように訳語が定義されている場合、`app/views/users/show.html.haml`では下記の呼び出し方で`users.show.title`を呼び出すことができます。このような呼び出し方を "lazy lookup" と呼びます。 682 | 683 | ```Ruby 684 | = t '.title' 685 | ``` 686 | 687 | * 688 | 訳語の呼び出しに用いるキーは、ドットを使った記法を利用しましょう。その方が`:scope`オプションを利用するより読みやすく、また辞書ファイルでの訳語の定義の階層がわかりやすいです。 689 | [[link](#dot-separated-keys)] 690 | 691 | ```Ruby 692 | # 悪い例 693 | I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages] 694 | 695 | # 良い例 696 | I18n.t 'activerecord.errors.messages.record_invalid' 697 | 698 | ``` 699 | 700 | * 701 | より詳細な内容は [Rails 702 | Guides](http://guides.rubyonrails.org/i18n.html) に譲ります。 703 | [[link](#i18n-guides)] 704 | 705 | ## Assets 706 | 707 | [assets pipeline](http://guides.rubyonrails.org/asset_pipeline.html) を使いましょう。 708 | 709 | * 710 | 独自のstylesheetファイル・javascriptファイル・画像ファイルは、`app/assets`配下に配置しましょう。 711 | [[link](#reserve-app-assets)] 712 | 713 | * 714 | 開発中のアプリケーションに必ずしもフィットしていない独自ライブラリは、`lib/assets`配下に配置しましょう。 715 | [[link](#lib-assets)] 716 | 717 | * 718 | [jQuery](http://jquery.com/)や 719 | [bootstrap](http://twitter.github.com/bootstrap/)のようなサードパーティーのコードは、`vendor/assets`配下に配置しましょう。 720 | [[link](#vendor-assets)] 721 | 722 | * 723 | 可能であれば、gem 化されたアセットを利用しましょう。 724 | (例: 725 | [jquery-rails](https://github.com/rails/jquery-rails), 726 | [jquery-ui-rails](https://github.com/joliss/jquery-ui-rails), 727 | [bootstrap-sass](https://github.com/thomas-mcdonald/bootstrap-sass), 728 | [zurb-foundation](https://github.com/zurb/foundation)). 729 | [[link](#gem-assets)] 730 | 731 | ## Mailers 732 | 733 | * 734 | mailer の名には `SomethingMailer`といったように`Mailer`を語尾につけ、その Mailer とどの view を結びついているか分かるようにしましょう 735 | [[link](#mailer-name)] 736 | 737 | * 738 | html と plain-text 両方での view templateを用意するようにしましょう。. 739 | [[link](#html-plain-email)] 740 | 741 | * 742 | development 環境では、メールの送信に失敗したらエラーが発生するように設定しておきましょう。デフォルトでは、development環境でのメール送信失敗はエラーとならないように設定されています。 743 | [[link](#enable-delivery-errors)] 744 | 745 | ```Ruby 746 | # config/environments/development.rb 747 | 748 | config.action_mailer.raise_delivery_errors = true 749 | ``` 750 | 751 | * 752 | development 環境ではローカルのSMTPサーバーは、[Mailcatcher](https://github.com/sj26/mailcatcher) のように利用しましょう。 753 | [[link](#local-smtp)] 754 | 755 | ```Ruby 756 | # config/environments/development.rb 757 | 758 | config.action_mailer.smtp_settings = { 759 | address: 'localhost', 760 | port: 1025, 761 | # more settings 762 | } 763 | ``` 764 | 765 | * 766 | host名を設定しましょう。 767 | [[link](#default-hostname)] 768 | 769 | ```Ruby 770 | # config/environments/development.rb 771 | config.action_mailer.default_url_options = { host: "#{local_ip}:3000" } 772 | 773 | # config/environments/production.rb 774 | config.action_mailer.default_url_options = { host: 'your_site.com' } 775 | 776 | # in your mailer class 777 | default_url_options[:host] = 'your_site.com' 778 | ``` 779 | 780 | * 781 | view で email へのリンクを記載する際には、`_path`でなく`_url`を利用しましょう。`_url` が生成するURLはホスト名を含みますが、`_path`メソッドのそれは含まない為です。 782 | [[link](#url-not-path-in-email)] 783 | 784 | ```Ruby 785 | # 悪い例 786 | 詳細は下記のリンクをご参照ください。 787 | = link_to 'こちら', course_path(@course) 788 | 789 | # 良い例 790 | 詳細は下記のリンクをご参照ください。 791 | = link_to 'こちら', course_url(@course) 792 | ``` 793 | 794 | * 795 | `from`と`to`は下記のような記法で記述するようにしましょう。 [[link](#email-addresses)] 796 | 797 | ```Ruby 798 | # in your mailer class 799 | default from: 'Your Name ' 800 | ``` 801 | 802 | * 803 | email 送信のテストでは、email 送信メソッドのプロトコルを`:test`に設定しましょう。 804 | [[link](#delivery-method-test)] 805 | 806 | ```Ruby 807 | # config/environments/test.rb 808 | 809 | config.action_mailer.delivery_method = :test 810 | ``` 811 | 812 | * 813 | 開発時と本番運用時には、email 送信メソッドのプロトコルは`:smtp`に設定しましょう。 814 | [[link](#delivery-method-smtp)] 815 | 816 | ```Ruby 817 | # config/environments/development.rb, config/environments/production.rb 818 | 819 | config.action_mailer.delivery_method = :smtp 820 | ``` 821 | 822 | * 823 | 外部の css ファイルを読み込めないメールクライアントがある為、html メールを送信する場合は、すべての style を template に直接記述するようにしましょう。styleをtemplateに直接記述した場合、template のコードの保守が非常に難しいものになりますが、 824 | [premailer-rails](https://github.com/fphilipe/premailer-rails) や 825 | [roadie](https://github.com/Mange/roadie) といった gem を使用することで、style や htmlタグを適切に編集することができます。 826 | [[link](#inline-email-styles)] 827 | 828 | * 829 | ページ描画と email の送信を同時に行うのはやめましょう。email が複数送信されると、ページのロードが遅延してリクエストがタイムアウトになる可能性があります。[sidekiq](https://github.com/mperham/sidekiq) のような gem を利用し、email をバックグラウンドのプロセスで送信することでこの問題を回避できます。 830 | [[link](#background-email)] 831 | 832 | 833 | ## Time 834 | 835 | * 836 | `application.rb` でtimezoneを適切に設定しましょう。 837 | [[link](#time-now)] 838 | 839 | ```Ruby 840 | config.time_zone = 'Eastern European Time' 841 | # optional - :utc か :local しか指定できません(デフォルトは:utcです) 842 | config.active_record.default_timezone = :local 843 | ``` 844 | 845 | * 846 | `Time.parse`は使わないようにしましょう。 847 | [[link](#time-parse)] 848 | 849 | ```Ruby 850 | # bad 851 | Time.parse('2015-03-02 19:05:37') # => システムのtimezoneを反映した時刻が返されます。 852 | 853 | # good 854 | Time.zone.parse('2015-03-02 19:05:37') # => Mon, 02 Mar 2015 19:05:37 EET +02:00 855 | ``` 856 | 857 | * 858 | `Time.now`は使わないようにしましょう。 859 | [[link](#time-now)] 860 | 861 | ```Ruby 862 | # bad 863 | Time.now # => システム日付を返します。その際、timezoneの設定は無視されます。 864 | 865 | # good 866 | Time.zone.now # => Fri, 12 Mar 2014 22:04:47 EET +02:00 867 | Time.current # 上記と同じ処理で、より短い記法です。 868 | ``` 869 | 870 | 871 | ## Bundler 872 | 873 | * 874 | 開発およびテストでしか利用しない gem は、`Gemfile`にて利用する環境(`development`や`test`)を指定しましょう。 875 | [[link](#dev-test-gems)] 876 | 877 | * 878 | 有名で利用者の多い gem を利用しましょう。もし、無名の gem を利用しなければならない場合は、利用前にソースコードをよく確認しましょう。 879 | [[link](#only-good-gems)] 880 | 881 | * 882 | gem にはOS固有のものがあります。もし、そのようなgemを利用しており、かつプロジェクトに参加している開発者が複数のOSを利用している場合、頻繁に 883 | `Gemfile.lock` が書き変わってしまいます。そのような状況を避けるため、`Gemfile`では OS X 特有のgem を `darwin` とグルーピングしましょう。同様に Linux 特有の gem は`linux` とグルーピングしましょう。 884 | [[link](#os-specific-gemfile-locks)] 885 | 886 | ```Ruby 887 | # Gemfile 888 | group :darwin do 889 | gem 'rb-fsevent' 890 | gem 'growl' 891 | end 892 | 893 | group :linux do 894 | gem 'rb-inotify' 895 | end 896 | ``` 897 | 898 | 適切な環境に適切なgemを`require`させるために、下記のコードを`config/application.rb`に追記しましょう。 899 | 900 | ```Ruby 901 | platform = RUBY_PLATFORM.match(/(linux|darwin)/)[0].to_sym 902 | Bundler.require(platform) 903 | ``` 904 | 905 | * 906 | `Gemfile.lock`はかならずバージョン管理しましょう。これはあなた方のプロジェクトの開発者全員が`bundle install`を実行する際に、同じバージョンの gem をインストールできるよう保証するためのものです。 907 | [[link](#gemfile-lock)] 908 | 909 | ## Flawed Gems 910 | 911 | 問題をはらんでいる、もしくは陳腐化した gem の一覧です。これらの gem は利用しないことをお勧めします。 912 | 913 | * [rmagick](http://rmagick.rubyforge.org/) 914 | * この gem は莫大なメモリ量を消費してしまいます。代わりに 915 | [minimagick](https://github.com/minimagick/minimagick) を使いましょう。 916 | 917 | * [autotest](http://www.zenspider.com/ZSS/Products/ZenTest/) 918 | * [guard](https://github.com/guard/guard) や 919 | [watchr](https://github.com/mynyml/watchr)の方が新しく優れているため、これらを利用しましょう。 920 | 921 | * [rcov](https://github.com/relevance/rcov) 922 | * コードカバレッジツールです。Ruby 1.9 以降に対応していないため、代わりに[SimpleCov](https://github.com/colszowka/simplecov)を使いましょう。 923 | 924 | 925 | * [therubyracer](https://github.com/cowboyd/therubyracer) 926 | * 莫大にメモリ量を消費するため、本番環境での利用は適当ではありません。 `node.js` を用いた方法をお勧めします。 927 | 928 | この一覧は随時更新していきます。もし有名で問題のある gem をご存知であれば、ご一報頂けると幸いです。 929 | 930 | ## Managing processes 931 | 932 | * 933 | プロジェクトが外部の複数のプロセスに依存している場合、[foreman](https://github.com/ddollar/foreman) を利用しましょう。 934 | [[link](#foreman)] 935 | 936 | # 参考文献 937 | 938 | この文書の他にもRailsのコーディングスタイルについて、優れた文献があります。時間があるときに目を通されてみることをお勧めします: 939 | 940 | * [The Rails 4 Way](http://www.amazon.com/The-Rails-Addison-Wesley-Professional-Ruby/dp/0321944275) 941 | * [Ruby on Rails Guides](http://guides.rubyonrails.org/) 942 | * [The RSpec Book](http://pragprog.com/book/achbd/the-rspec-book) 943 | * [The Cucumber Book](http://pragprog.com/book/hwcuc/the-cucumber-book) 944 | * [Everyday Rails Testing with RSpec](https://leanpub.com/everydayrailsrspec) 945 | * [Better Specs for RSpec](http://betterspecs.org) 946 | 947 | # 貢献 948 | 949 | このガイドに書いてあることはすべて編集可能です。 Railsのコードスタイルに興味のある全ての人と共に取り組むことが私の望みです。 究極的には、全てのRubyコミュニティにとって有益なガイドを作ることができればと思っています。 950 | 遠慮せずチケットを立てたりプルリクエストを送ったりしてください。 951 | また、このプロジェクト(とRubocop)への金銭的な貢献は、[gittip](https://www.gittip.com/bbatsov)経由で行うことができます。 952 | 953 | [![Support via Gittip](https://rawgithub.com/twolfson/gittip-badge/0.2.0/dist/gittip.png)](https://www.gittip.com/bbatsov) 954 | 955 | ## 貢献するには 956 | 957 | 簡単です! [contribution guidelines](https://github.com/bbatsov/rails-style-guide/blob/master/CONTRIBUTING.md) をご覧ください! 958 | 959 | # ライセンス 960 | 961 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png)この著作物は、 [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/deed.en_US)に従います。 962 | 963 | # このガイドを広めてください 964 | 965 | このガイドは有志のコミュニティによって作成されるものです。そもそも存在が世に知られないと、このガイド自体が意味のないものになってしまいます。このページをご覧になった方には、ぜひこのガイドについてTwitterでつぶやいたり、友達や同僚にシェアして、このガイドの存在を広めていただけるようお願いします。 全てのコメント・提案・意見がこのガイドをより良いものにしていきます。 966 | 967 | 親愛をこめて
968 | [Bozhidar](https://twitter.com/bbatsov) 969 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 序 2 | 3 | > “ロールモデルが重要なのだ。”
4 | > -- アレックス・マーフィー巡査 / 映画『ロボコップ』の登場人物 5 | 6 | このガイドの目的は、Ruby on Rails 4 開発における コーディングスタイルのベストプラクティスを提供することです。すでに有志によって作成された[Ruby coding style guide](https://github.com/bbatsov/ruby-style-guide)の補足資料にあたります。 7 | 8 | 記載内容の一部は Rails 4.0 以上のみを対象としています。 9 | 10 | PDF形式やHTML形式のコピーは[Transmuter](https://github.com/TechnoGate/transmuter)を使って作成できます。 11 | 12 | 13 | 以下の言語の翻訳が利用可能です: 14 | 15 | * [中国語(簡体)](https://github.com/JuanitoFatas/rails-style-guide/blob/master/README-zhCN.md) 16 | * [中国語(繁体)](https://github.com/JuanitoFatas/rails-style-guide/blob/master/README-zhTW.md) 17 | * [日本語](hhttps://github.com/satour/rails-style-guide/blob/master/README-jaJA.md) 18 | * [ロシア語](https://github.com/arbox/rails-style-guide/blob/master/README-ruRU.md) 19 | * [トルコ語](https://github.com/tolgaavci/rails-style-guide/blob/master/README-trTR.md) 20 | 21 | # The Rails Style Guide 22 | 23 | このガイドは、Rails開発の実務におけるコーディングスタイルのベストプラクティスを目指したものです。開発における理想論は多くありますが、このガイドはあくまで実務での利用に役立つことを目的としています。このガイドの内容は絶対ではありませんが、非常に多くのRails開発者のフィードバックや資料を基にして書かれたものです。ここで改めて、彼らへ多大な感謝を示します。 24 | 25 | ## 目次 26 | 27 | * [Configuration](#configuration) 28 | * [Routing](#routing) 29 | * [Controllers](#controllers) 30 | * [Models](#models) 31 | * [ActiveRecord](#activerecord) 32 | * [ActiveRecord Queries](#activerecord-queries) 33 | * [Migrations](#migrations) 34 | * [Views](#views) 35 | * [Internationalization](#internationalization) 36 | * [Assets](#assets) 37 | * [Mailers](#mailers) 38 | * [Time](#time) 39 | * [Bundler](#bundler) 40 | * [Flawed Gems](#flawed-gems) 41 | * [Managing processes](#managing-processes) 42 | 43 | ## Configuration 44 | 45 | * 46 | アプリケーション起動時の処理をカスタマイズしたい場合は、 `config/initializers` 配下にその処理を記述したコードを配置しましょう。`config/initializers` 配下のコードはアプリケーション起動時に実行されます。 47 | [[link](#config-initializers)] 48 | 49 | * 50 | gem の初期化に必要なコードは、gem 毎に作成しましょう。また、そのファイルの名前は gem の名前と同じにしましょう。例えば、 `carrierwave.rb`、 `active_admin.rb`などです。 51 | [[link](#gem-initializers)] 52 | 53 | * 54 | Railsには3つの環境(development、test、 production)がありますが、環境毎に適切な設定をしましょう。 55 | ( `config/environments/`配下にそれぞれの環境に対応した設定ファイルが配置してあります。) 56 | [[link](#dev-test-prod-configs)] 57 | 58 | * もしプリコンパイルを行う場合は、追加するアセット名を明記しましょう。: 59 | 60 | ```Ruby 61 | # config/environments/production.rb 62 | # Precompile additional assets (application.js, application.css, 63 | #and all non-JS/CSS are already added) 64 | config.assets.precompile += %w( rails_admin/rails_admin.css rails_admin/rails_admin.js ) 65 | ``` 66 | 67 | * 68 | 設定をすべての環境に適用したい場合は、 `config/application.rb` に記述しましょう. 69 | [[link](#app-config)] 70 | 71 | * 72 | `production`環境と同環境の `staging` 環境を作成しておきましょう。 73 | [[link](#staging-like-prod)] 74 | 75 | ## Routing 76 | 77 | * 78 | もしRESTfulなresourceにアクションを追加する場合(そのようなアクションが本当に必要かはわかりませんが)、 `member` と `collection` を利用しましょう。 79 | [[link](#member-collection-routes)] 80 | 81 | ```Ruby 82 | # 悪い例 83 | get 'subscriptions/:id/unsubscribe' 84 | resources :subscriptions 85 | 86 | # 良い例 87 | resources :subscriptions do 88 | get 'unsubscribe', on: :member 89 | end 90 | 91 | # 悪い例 92 | get 'photos/search' 93 | resources :photos 94 | 95 | # 良い例 96 | resources :photos do 97 | get 'search', on: :collection 98 | end 99 | ``` 100 | 101 | * 102 | 複数の`member/collection`を定義しなければいけない場合は、ブロック構文を利用しましょう。[[link](#many-member-collection-routes)] 103 | 104 | 105 | ```Ruby 106 | resources :subscriptions do 107 | member do 108 | get 'unsubscribe' 109 | # more routes 110 | end 111 | end 112 | 113 | resources :photos do 114 | collection do 115 | get 'search' 116 | # more routes 117 | end 118 | end 119 | ``` 120 | 121 | * 122 | ActiveRecordのモデル間の関連を表現するには、入れ子型でルートを定義すると分かりやすいでしょう。[[link](#nested-routes)] 123 | 124 | ```Ruby 125 | class Post < ActiveRecord::Base 126 | has_many :comments 127 | end 128 | 129 | class Comments < ActiveRecord::Base 130 | belongs_to :post 131 | end 132 | 133 | # routes.rb 134 | resources :posts do 135 | resources :comments 136 | end 137 | ``` 138 | 139 | * 140 | 関連する アクション・ルートをまとめるには `namespace`を利用しましょう。[[link](#namespaced-routes)] 141 | 142 | ```Ruby 143 | namespace :admin do 144 | # Directs /admin/products/* to Admin::ProductsController 145 | # (app/controllers/admin/products_controller.rb) 146 | resources :products 147 | end 148 | ``` 149 | 150 | * 151 | Railsに昔あった古いルーティング記法は絶対に利用しないようにしましょう。この記法を利用した場合、すべてのアクションへのすべてのGETリクエストを許可してしまいます。[[link](#no-wild-routes)] 152 | 153 | ```Ruby 154 | # 非常に悪い例 155 | match ':controller(/:action(/:id(.:format)))' 156 | ``` 157 | 158 | * 159 | `match` を利用しないようにしましょう。もし利用する必要がある場合は、アクション毎に `:via` オプションで`[:get, :post, :patch, :put, :delete]`を指定しましょう。 [[link](#no-match-routes)] 160 | 161 | ## Controllers 162 | 163 | * 164 | ビジネスロジックは controller でなく model に書きましょう。controller の役割は、view層にデータを渡すこと、またはview層からデータを受け取ることのいずれかのみです。それ以外のコードは controller に記述しないようにしましょう。[[link](#skinny-controllers)] 165 | 166 | * 167 | (理想論ですが)すべての controller は find と new 以外のメソッドはひとつ程度に留められるようにしましょう。[[link](#one-method)] 168 | 169 | * 170 | controller と view の間でやりとりするインスタンス変数は2つまでに留めておきましょう。[[link](#shared-instance-variables)] 171 | 172 | ## Models 173 | 174 | * 175 | ActiveRecord を継承しないモデルも導入しましょう。 176 | [[link](#model-classes)] 177 | 178 | * 179 | モデルの名前は、意味が通じてなおかつ短いものにしましょう。その際には省略語は利用しないようにしましょう。 180 | [[link](#meaningful-model-names)] 181 | 182 | * 183 | ActiveRecordのような振る舞い(validationなど)が必要なモデルには、[ActiveAttr](https://github.com/cgriego/active_attr) 184 | のような gem を使いましょう. 185 | [[link](#activeattr-gem)] 186 | 187 | ```Ruby 188 | class Message 189 | include ActiveAttr::Model 190 | 191 | attribute :name 192 | attribute :email 193 | attribute :content 194 | attribute :priority 195 | 196 | attr_accessible :name, :email, :content 197 | 198 | validates :name, presence: true 199 | validates :email, format: { with: /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i } 200 | validates :content, length: { maximum: 500 } 201 | end 202 | ``` 203 | 204 | 詳細な例は[RailsCast on the subject](http://railscasts.com/episodes/326-activeattr)に譲ります。 205 | 206 | ### ActiveRecord 207 | 208 | * 209 | データベースの操作を自由に出来ない等、特別な理由がない限り、ActiveRecord の初期値(テーブル名、主キー等)を変更しないようにしましょう。 210 | [[link](#keep-ar-defaults)] 211 | 212 | ```Ruby 213 | # 悪い例 214 | class Transaction < ActiveRecord::Base 215 | self.table_name = 'order' 216 | ... 217 | end 218 | ``` 219 | 220 | * 221 | `has_many`や`validates`などはクラス定義の最初の方に記述しましょう。(satour注:本文と例が一致していません@原文) 222 | [[link](#macro-style-methods)] 223 | 224 | ```Ruby 225 | class User < ActiveRecord::Base 226 | # 一番上にデフォルト・スコープを記述する。 227 | default_scope { where(active: true) } 228 | 229 | # 定数を記述する。 230 | COLORS = %w(red green blue) 231 | 232 | # attr関連のマクロを記述する。 233 | attr_accessor :formatted_date_of_birth 234 | 235 | attr_accessible :login, :first_name, :last_name, :email, :password 236 | 237 | # アソシエーションに関するマクロを記述する。 238 | belongs_to :country 239 | 240 | has_many :authentications, dependent: :destroy 241 | 242 | # ヴァリデーションに関するマクロを記述する。 243 | validates :email, presence: true 244 | validates :username, presence: true 245 | validates :username, uniqueness: { case_sensitive: false } 246 | validates :username, format: { with: /\A[A-Za-z][A-Za-z0-9._-]{2,19}\z/ } 247 | validates :password, format: { with: /\A\S{8,128}\z/, allow_nil: true} 248 | 249 | # コールバックを記述する。 250 | before_save :cook 251 | before_save :update_username_lower 252 | 253 | # 上記以外のマクロがある場合、コールバックの下に続けて記述する。 254 | 255 | ... 256 | end 257 | ``` 258 | 259 | * 260 | なるべく`has_and_belongs_to_many`より`has_many :through`を利用しましょう。`has_many :through` を使うと model を join する際に属性やヴァリデーションを利用することが出来ます。 261 | [[link](#has-many-through)] 262 | 263 | ```Ruby 264 | # あまり良くない例 265 | class User < ActiveRecord::Base 266 | has_and_belongs_to_many :groups 267 | end 268 | 269 | class Group < ActiveRecord::Base 270 | has_and_belongs_to_many :users 271 | end 272 | 273 | # 良い例 274 | class User < ActiveRecord::Base 275 | has_many :memberships 276 | has_many :groups, through: :memberships 277 | end 278 | 279 | class Membership < ActiveRecord::Base 280 | belongs_to :user 281 | belongs_to :group 282 | end 283 | 284 | class Group < ActiveRecord::Base 285 | has_many :memberships 286 | has_many :users, through: :memberships 287 | end 288 | ``` 289 | 290 | * 291 | なるべく`read_attribute(:attribute)`より`self[:attribute]`を利用しましょう。 292 | [[link](#read-attribute)] 293 | 294 | ```Ruby 295 | # 悪い例 296 | def amount 297 | read_attribute(:amount) * 100 298 | end 299 | 300 | # 良い例 301 | def amount 302 | self[:amount] * 100 303 | end 304 | ``` 305 | 306 | * 307 | なるべく`write_attribute(:attribute, value)`より`self[:attribute] = value`を利用しましょう。 308 | [[link](#write-attribute)] 309 | 310 | ```Ruby 311 | # 悪い例 312 | def amount 313 | write_attribute(:amount, 100) 314 | end 315 | 316 | # 良い例 317 | def amount 318 | self[:amount] = 100 319 | end 320 | ``` 321 | 322 | * 323 | ["sexy" 324 | validations](http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/) を利用しましょう。 325 | [[link](#sexy-validations)] 326 | 327 | ```Ruby 328 | # 悪い例 329 | validates_presence_of :email 330 | 331 | # 良い例 332 | validates :email, presence: true 333 | ``` 334 | 335 | * 336 | 独自のヴァリデーションが2回以上呼び出される場合、もしくは独自のヴァリデーションが正規表現を含む場合は、ファイルとして切り出しましょう。 337 | [[link](#custom-validator-file)] 338 | 339 | ```Ruby 340 | # 悪い例 341 | class Person 342 | validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i } 343 | end 344 | 345 | # 良い例 346 | class EmailValidator < ActiveModel::EachValidator 347 | def validate_each(record, attribute, value) 348 | record.errors[attribute] << (options[:message] || 'is not a valid email') unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i 349 | end 350 | end 351 | 352 | class Person 353 | validates :email, email: true 354 | end 355 | ``` 356 | 357 | * 358 | 独自のヴァリデーション・ファイルは`app/validators`を作成し、その配下に配置しましょう。 359 | [[link](#app-validators)] 360 | 361 | * 362 | 独自のヴァリデーションを使って複数のアプリケーションをメンテナンスしている場合、もしくはそのヴァリデーションが汎用的な内容である場合、gem 化することを検討しましょう。 363 | [[link](#custom-validators-gem)] 364 | 365 | * 366 | 名前付きスコープを取り入れましょう。 367 | [[link](#named-scopes)] 368 | 369 | ```Ruby 370 | class User < ActiveRecord::Base 371 | scope :active, -> { where(active: true) } 372 | scope :inactive, -> { where(active: false) } 373 | 374 | scope :with_orders, -> { joins(:orders).select('distinct(users.id)') } 375 | end 376 | ``` 377 | 378 | * 379 | 名前付きスコープがラムダ式で定義されており、かつ引数が複雑になってきた際には、スコープ名と同名の`ActiveRecord::Relation`オブジェクトを返すクラスメソッドを作成することが望ましいです。そうすることで記述を簡潔にすることができます。 380 | [[link](#named-scope-class)] 381 | 382 | ```Ruby 383 | class User < ActiveRecord::Base 384 | def self.with_orders 385 | joins(:orders).select('distinct(users.id)') 386 | end 387 | end 388 | ``` 389 | 390 | * 391 | [`update_attribute`](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute) は`update_attributes`と異なり、モデルのヴァリデーション実行をスキップするので、利用する際は気をつけましょう。 392 | [[link](#beware-update-attribute)] 393 | 394 | * 395 | ユーザー・フレンドリーな URL を用意しましょう。下記に例を示します。 396 | [[link](#user-friendly-urls)] 397 | 398 | * ここでは、`to_param` を上書きします。このメソッドはRailsによるURL作成に使用されます。デフォルトの実装ではレコードの`id`を`String`型で返します。 399 | 400 | ```Ruby 401 | class Person 402 | def to_param 403 | "#{id} #{name}".parameterize 404 | end 405 | end 406 | ``` 407 | 408 | * `to_param`の返り値をURL-friendlyな値にするために, 文字列を`parameterize` します。`parameterize`ではオブジェクトをActiveRecordの`find`メソッドで検索できるようにする為、`id`を文字列の一番先頭に置きます。 409 | 410 | * `friendly_id`という gem を利用しましょう。`id`のかわりに model の他の属性を使って、読みやすいURLを生成することが出来ます。 411 | 412 | ```Ruby 413 | class Person 414 | extend FriendlyId 415 | friendly_id :name, use: :slugged 416 | end 417 | ``` 418 | 419 | より詳細な内容は [gem documentation](https://github.com/norman/friendly_id) に譲ります。 420 | 421 | * 422 | ActiveRecordのオブジェクトに対して繰り返し処理を行う場合は、`find_each`を利用しましょう。(`all`などで)DBから取得したレコードセットを直接繰り返し処理させる場合、すべてのオブジェクトを即時にインスタンス化することが求められ、大量にメモリを消費します。`find_each`はインスタンス化を逐次処理にできるため、メモリ量の消費を抑制することが出来ます。 423 | [[link](#find-each)] 424 | 425 | 426 | ```Ruby 427 | # 悪い例 428 | Person.all.each do |person| 429 | person.do_awesome_stuff 430 | end 431 | 432 | Person.where('age > 21').each do |person| 433 | person.party_all_night! 434 | end 435 | 436 | # 良い例 437 | Person.find_each do |person| 438 | person.do_awesome_stuff 439 | end 440 | 441 | Person.where('age > 21').find_each do |person| 442 | person.party_all_night! 443 | end 444 | ``` 445 | 446 | * 447 | [Rails creates callbacks for dependent 448 | associations](https://github.com/rails/rails/issues/3458) により、 449 | `before_destroy`には`prepend: true`オプションを付けましょう。(satour注:リンク先の内容がタイトルから連想される内容と異なる。またリンク先のissueはcloseされている。) 450 | 451 | ```Ruby 452 | # 悪い例 (super_admin? が true でもrolesが自動的にdeleteされる。) 453 | has_many :roles, dependent: :destroy 454 | 455 | before_destroy :ensure_deletable 456 | 457 | def ensure_deletable 458 | fail "Cannot delete super admin." if super_admin? 459 | end 460 | 461 | # 良い例 462 | has_many :roles, dependent: :destroy 463 | 464 | before_destroy :ensure_deletable, prepend: true 465 | 466 | def ensure_deletable 467 | fail "Cannot delete super admin." if super_admin? 468 | end 469 | ``` 470 | 471 | ### ActiveRecord Queries 472 | 473 | * 474 | SQLインジェクション攻撃を防ぐため、 475 | クエリの文字列の中で式を展開するのはやめましょう。 476 | [[link](#avoid-interpolation)] 477 | 478 | ```Ruby 479 | # bad - paramがエスケープされず、SQLインジェクションの可能性が残る。 480 | Client.where("orders_count = #{params[:orders]}") 481 | 482 | # good - paramがエスケープされる 483 | Client.where('orders_count = ?', params[:orders]) 484 | ``` 485 | 486 | * 487 | クエリのなかで2つ以上のプレースホルダを使う場合は、 488 | 名前付きプレースホルダを利用しましょう。 489 | [[link](#named-placeholder)] 490 | 491 | ```Ruby 492 | # okish 493 | Client.where( 494 | 'created_at >= ? AND created_at <= ?', 495 | params[:start_date], params[:end_date] 496 | ) 497 | 498 | # good 499 | Client.where( 500 | 'created_at >= :start_date AND created_at <= :end_date', 501 | start_date: params[:start_date], end_date: params[:end_date] 502 | ) 503 | ``` 504 | 505 | * 506 | idを指定してひとつのレコードを取得する場合は、`where`より`find`を使いましょう。 507 | [[link](#find)] 508 | 509 | ```Ruby 510 | # bad 511 | User.where(id: id).take 512 | 513 | # good 514 | User.find(id) 515 | ``` 516 | 517 | * 518 | 複数の属性を指定してひとつのレコードを取得する場合は、`where`より`find_by`を使いましょう。 519 | 520 | [[link](#find_by)] 521 | 522 | ```Ruby 523 | # bad 524 | User.where(first_name: 'Bruce', last_name: 'Wayne').first 525 | 526 | # good 527 | User.find_by(first_name: 'Bruce', last_name: 'Wayne')) 528 | ``` 529 | 530 | * 531 | 大量のレコードを処理しなければいけない場合は、`find_each`を使いましょう。 532 | [[link](#find_each)] 533 | 534 | ```Ruby 535 | # bad - すべてのレコードを一度に読み込む 536 | # users テーブルに数千行のレコードがあった場合、 537 | この書き方では非常に非効率になる。 538 | User.all.each do |user| 539 | NewsMailer.weekly(user).deliver_now 540 | end 541 | 542 | # good - バッチのなかでレコードが読み込まれる 543 | User.find_each do |user| 544 | NewsMailer.weekly(user).deliver_now 545 | end 546 | ``` 547 | 548 | * 549 | SQLのようにクエリを記述する場合、`where.not`を使った方がよいケースがあります。 550 | [[link](#where-not)] 551 | 552 | ```Ruby 553 | # bad 554 | User.where("id != ?", id) 555 | 556 | # good 557 | User.where.not(id: id) 558 | ``` 559 | 560 | ## Migrations 561 | 562 | * 563 | `schema.rb` (または `structure.sql`) は必ずバージョン管理しましょう。 564 | [[link](#schema-version)] 565 | 566 | * 567 | 最新のスキーマで空のデータベースを作る際には、`rake db:migrate`でなく`rake db:schema:load`を利用しましょう。 568 | [[link](#db-schema-load)] 569 | 570 | * 571 | フィールドの初期値の設定処理は、アプリケーションの中に記述せず、migration ファイルに記述しましょう。 572 | [[link](#default-migration-values)] 573 | 574 | ```Ruby 575 | # 悪い例 - アプリケーションでデフォルト値を設定している。 576 | def amount 577 | self[:amount] or 0 578 | end 579 | ``` 580 | 581 | 多くのRails開発者が、初期値の設定をRailsのアプリケーション層だけで行っています。しかし、そのやり方はデータの不整合やアプリケーションのバグを引き起こす可能性が高いです。また、重要なアプリケーションは、データベースを他のアプリケーションと共有している場合が多く、単体のRailsアプリケーションでデータ保全性を担保するのは不可能です。 582 | 583 | * 584 | 外部キー制約を設定しましょう。Railは4.2から外部キー制約をサポートしています。 585 | [[link](#foreign-key-constraints)] 586 | 587 | * 588 | スキーマを変更する(テーブルの追加、フィールドの追加など)migrationを書くときは、`up`や`down`でなく`change`を利用しましょう。 589 | [[link](#change-vs-up-down)] 590 | 591 | ```Ruby 592 | # 古い書き方(古いバージョンのRailsではこのような書き方しか出来ませんでした。) 593 | class AddNameToPeople < ActiveRecord::Migration 594 | def up 595 | add_column :people, :name, :string 596 | end 597 | 598 | def down 599 | remove_column :people, :name 600 | end 601 | end 602 | 603 | # こちらの方が好ましい 604 | class AddNameToPeople < ActiveRecord::Migration 605 | def change 606 | add_column :people, :name, :string 607 | end 608 | end 609 | ``` 610 | 611 | * 612 | migration でモデルを利用してはいけません。モデルの内容は更新されていくものであり、migration でモデルを引用していた場合、migrationの実行時に不具合を起こす可能性が高いです。 613 | [[link](#no-model-class-migrations)] 614 | 615 | ## Views 616 | 617 | * 618 | viewから直接、モデル層を呼び出さないようにしましょう。 619 | [[link](#no-direct-model-view)] 620 | 621 | * 622 | Viewでの表示のための複雑なフォーマット処理をviewのファイルに記述してはいけません。ヘルパーメソッドに書き出しましょう。 623 | [[link](#no-complex-view-formatting)] 624 | 625 | * 626 | 同じコードを複数箇所に書くのは非効率です。複数のviewで同じコードを書く場合は、部分テンプレートやレイアウトにまとめましょう。 627 | [[link](#partials)] 628 | 629 | ## Internationalization 630 | 631 | * 632 | 国際化(国や土地によって文字列を翻訳する)したい文字列は、すべて`config/locales`配下のlocaleファイル(辞書ファイル)で定義しましょう。 633 | [[link](#locale-texts)] 634 | 635 | * 636 | 国際化する場合、ActiveRecordのmodelのラベルには必ず対訳が必要です。各辞書ファイルで`activerecord` スコープを使って対訳を定義しましょう。 637 | [[link](#translated-labels)] 638 | 639 | ``` 640 | en: 641 | activerecord: 642 | models: 643 | user: Member 644 | attributes: 645 | user: 646 | name: 'Full name' 647 | ``` 648 | 649 | この場合、`User.model_name.human` は "Member" を返し、`User.human_attribute_name("name")` は "Full name" を返します。これらの対訳はviewでのラベル表示で使用されます。 650 | 651 | 652 | * 653 | ActiveRecord の model の対訳と view で使用するテキストは別々の辞書ファイルに定義しましょう。model の対訳は`model`ディレクトリを作成しその配下に辞書ファイルを作成しましょう。また view での用いる対訳は`views`ディレクトリを作成し、その配下に辞書ファイルを作成しましょう. 654 | [[link](#organize-locale-files)] 655 | 656 | * 辞書ファイルを格納したディレクトリが分散する場合、 `application.rb` で辞書ファイルを格納しているディレクトリを指定する必要があります。 657 | 658 | ```Ruby 659 | # config/application.rb 660 | config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')] 661 | ``` 662 | 663 | * 664 | データフォーマットや通貨表記など、どのlocaleでも共通して利用したい文字列は、`locales` 直下にファイルを作成しそこに定義しましょう。 665 | [[link](#shared-localization)] 666 | 667 | * 668 | 挙動が同じなら、利用するメソッドは名称が短い方が望ましいです。`I18n.translate`ではなく`I18n.t`を使いましょう。また、`I18n.localize`でなく、`I18n.l`を使いましょう。 669 | [[link](#short-i18n)] 670 | 671 | * 672 | View では、"lazy lookup" を利用しましょう。 673 | [[link](#lazy-lookup)] 674 | 675 | ``` 676 | en: 677 | users: 678 | show: 679 | title: 'User details page' 680 | ``` 681 | 682 | 辞書ファイルでこのように訳語が定義されている場合、`app/views/users/show.html.haml`では下記の呼び出し方で`users.show.title`を呼び出すことができます。このような呼び出し方を "lazy lookup" と呼びます。 683 | 684 | ```Ruby 685 | = t '.title' 686 | ``` 687 | 688 | * 689 | 訳語の呼び出しに用いるキーは、ドットを使った記法を利用しましょう。その方が`:scope`オプションを利用するより読みやすく、また辞書ファイルでの訳語の定義の階層がわかりやすいです。 690 | [[link](#dot-separated-keys)] 691 | 692 | ```Ruby 693 | # 悪い例 694 | I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages] 695 | 696 | # 良い例 697 | I18n.t 'activerecord.errors.messages.record_invalid' 698 | 699 | ``` 700 | 701 | * 702 | より詳細な内容は [Rails 703 | Guides](http://guides.rubyonrails.org/i18n.html) に譲ります。 704 | [[link](#i18n-guides)] 705 | 706 | ## Assets 707 | 708 | [assets pipeline](http://guides.rubyonrails.org/asset_pipeline.html) を使いましょう。 709 | 710 | * 711 | 独自のstylesheetファイル・javascriptファイル・画像ファイルは、`app/assets`配下に配置しましょう。 712 | [[link](#reserve-app-assets)] 713 | 714 | * 715 | 開発中のアプリケーションに必ずしもフィットしていない独自ライブラリは、`lib/assets`配下に配置しましょう。 716 | [[link](#lib-assets)] 717 | 718 | * 719 | [jQuery](http://jquery.com/)や 720 | [bootstrap](http://twitter.github.com/bootstrap/)のようなサードパーティーのコードは、`vendor/assets`配下に配置しましょう。 721 | [[link](#vendor-assets)] 722 | 723 | * 724 | 可能であれば、gem 化されたアセットを利用しましょう。 725 | (例: 726 | [jquery-rails](https://github.com/rails/jquery-rails), 727 | [jquery-ui-rails](https://github.com/joliss/jquery-ui-rails), 728 | [bootstrap-sass](https://github.com/thomas-mcdonald/bootstrap-sass), 729 | [zurb-foundation](https://github.com/zurb/foundation)). 730 | [[link](#gem-assets)] 731 | 732 | ## Mailers 733 | 734 | * 735 | mailer の名には `SomethingMailer`といったように`Mailer`を語尾につけ、その Mailer とどの view を結びついているか分かるようにしましょう 736 | [[link](#mailer-name)] 737 | 738 | * 739 | html と plain-text 両方での view templateを用意するようにしましょう。. 740 | [[link](#html-plain-email)] 741 | 742 | * 743 | delelopment 環境では、メールの送信に失敗したらエラーが発生するように設定しておきましょう。デフォルトでは、develepment環境でのメール送信失敗はエラーとならないように設定されています。 744 | [[link](#enable-delivery-errors)] 745 | 746 | ```Ruby 747 | # config/environments/development.rb 748 | 749 | config.action_mailer.raise_delivery_errors = true 750 | ``` 751 | 752 | * 753 | development 環境ではローカルのSMTPサーバーは、[Mailcatcher](https://github.com/sj26/mailcatcher) のように利用しましょう。 754 | [[link](#local-smtp)] 755 | 756 | ```Ruby 757 | # config/environments/development.rb 758 | 759 | config.action_mailer.smtp_settings = { 760 | address: 'localhost', 761 | port: 1025, 762 | # more settings 763 | } 764 | ``` 765 | 766 | * 767 | host名を設定しましょう。 768 | [[link](#default-hostname)] 769 | 770 | ```Ruby 771 | # config/environments/development.rb 772 | config.action_mailer.default_url_options = { host: "#{local_ip}:3000" } 773 | 774 | # config/environments/production.rb 775 | config.action_mailer.default_url_options = { host: 'your_site.com' } 776 | 777 | # in your mailer class 778 | default_url_options[:host] = 'your_site.com' 779 | ``` 780 | 781 | * 782 | view で email へのリンクを記載する際には、`_path`でなく`_url`を利用しましょう。`_url` が生成するURLはホスト名を含みますが、`_path`メソッドのそれは含まない為です。 783 | [[link](#url-not-path-in-email)] 784 | 785 | ```Ruby 786 | # 悪い例 787 | 詳細は下記のリンクをご参照ください。 788 | = link_to 'こちら', course_path(@course) 789 | 790 | # 良い例 791 | 詳細は下記のリンクをご参照ください。 792 | = link_to 'こちら', course_url(@course) 793 | ``` 794 | 795 | * 796 | `from`と`to`は下記のような記法で記述するようにしましょう。 [[link](#email-addresses)] 797 | 798 | ```Ruby 799 | # in your mailer class 800 | default from: 'Your Name ' 801 | ``` 802 | 803 | * 804 | email 送信のテストでは、email 送信メソッドのプロトコルを`:test`に設定しましょう。 805 | [[link](#delivery-method-test)] 806 | 807 | ```Ruby 808 | # config/environments/test.rb 809 | 810 | config.action_mailer.delivery_method = :test 811 | ``` 812 | 813 | * 814 | 開発時と本番運用時には、email 送信メソッドのプロトコルは`:smtp`に設定しましょう。 815 | [[link](#delivery-method-smtp)] 816 | 817 | ```Ruby 818 | # config/environments/development.rb, config/environments/production.rb 819 | 820 | config.action_mailer.delivery_method = :smtp 821 | ``` 822 | 823 | * 824 | 外部の css ファイルを読み込めないメールクライアントがある為、html メールを送信する場合は、すべての style を template に直接記述するようにしましょう。styleをtemplateに直接記述した場合、template のコードの保守が非常に難しいものになりますが、 825 | [premailer-rails](https://github.com/fphilipe/premailer-rails) や 826 | [roadie](https://github.com/Mange/roadie) といった gem を使用することで、style や htmlタグを適切に編集することができます。 827 | [[link](#inline-email-styles)] 828 | 829 | * 830 | ページ描画と email の送信を同時に行うのはやめましょう。email が複数送信されると、ページのロードが遅延してリクエストがタイムアウトになる可能性があります。[sidekiq](https://github.com/mperham/sidekiq) のような gem を利用し、email をバックグラウンドのプロセスで送信することでこの問題を回避できます。 831 | [[link](#background-email)] 832 | 833 | 834 | ## Time 835 | 836 | * 837 | `application.rb` でtimezoneを適切に設定しましょう。 838 | [[link](#time-now)] 839 | 840 | ```Ruby 841 | config.time_zone = 'Eastern European Time' 842 | # optional - :utc か :local しか指定できません(デフォルトは:utcです) 843 | config.active_record.default_timezone = :local 844 | ``` 845 | 846 | * 847 | `Time.parse`は使わないようにしましょう。 848 | [[link](#time-parse)] 849 | 850 | ```Ruby 851 | # bad 852 | Time.parse('2015-03-02 19:05:37') # => システムのtimezoneを反映した時刻が返されます。 853 | 854 | # good 855 | Time.zone.parse('2015-03-02 19:05:37') # => Mon, 02 Mar 2015 19:05:37 EET +02:00 856 | ``` 857 | 858 | * 859 | `Time.now`は使わないようにしましょう。 860 | [[link](#time-now)] 861 | 862 | ```Ruby 863 | # bad 864 | Time.now # => システム日付を返します。その際、timezoneの設定は無視されます。 865 | 866 | # good 867 | Time.zone.now # => Fri, 12 Mar 2014 22:04:47 EET +02:00 868 | Time.current # 上記と同じ処理で、より短い記法です。 869 | ``` 870 | 871 | 872 | ## Bundler 873 | 874 | * 875 | 開発およびテストでしか利用しない gem は、`Gemfile`にて利用する環境(`development`や`test`)を指定しましょう。 876 | [[link](#dev-test-gems)] 877 | 878 | * 879 | 有名で利用者の多い gem を利用しましょう。もし、無名の gem を利用しなければならない場合は、利用前にソースコードをよく確認しましょう。 880 | [[link](#only-good-gems)] 881 | 882 | * 883 | gem にはOS固有のものがあります。もし、そのようなgemを利用しており、かつプロジェクトに参加している開発者が複数のOSを利用している場合、頻繁に 884 | `Gemfile.lock` が書き変わってしまいます。そのような状況を避けるため、`Gemfile`では OS X 特有のgem を `darwin` とグルーピングしましょう。同様に Linux 特有の gem は`linux` とグルーピングしましょう。 885 | [[link](#os-specific-gemfile-locks)] 886 | 887 | ```Ruby 888 | # Gemfile 889 | group :darwin do 890 | gem 'rb-fsevent' 891 | gem 'growl' 892 | end 893 | 894 | group :linux do 895 | gem 'rb-inotify' 896 | end 897 | ``` 898 | 899 | 適切な環境に適切なgemを`require`させるために、下記のコードを`config/application.rb`に追記しましょう。 900 | 901 | ```Ruby 902 | platform = RUBY_PLATFORM.match(/(linux|darwin)/)[0].to_sym 903 | Bundler.require(platform) 904 | ``` 905 | 906 | * 907 | `Gemfile.lock`はかならずバージョン管理しましょう。これはあなた方のプロジェクトの開発者全員が`bundle install`を実行する際に、同じバージョンの gem をインストールできるよう保証するためのものです。 908 | [[link](#gemfile-lock)] 909 | 910 | ## Flawed Gems 911 | 912 | 問題をはらんでいる、もしくは陳腐化した gem の一覧です。これらの gem は利用しないことをお勧めします。 913 | 914 | * [rmagick](http://rmagick.rubyforge.org/) 915 | * この gem は莫大なメモリ量を消費してしまいます。代わりに 916 | [minimagick](https://github.com/minimagick/minimagick) を使いましょう。 917 | 918 | * [autotest](http://www.zenspider.com/ZSS/Products/ZenTest/) 919 | * [guard](https://github.com/guard/guard) や 920 | [watchr](https://github.com/mynyml/watchr)の方が新しく優れているため、これらを利用しましょう。 921 | 922 | * [rcov](https://github.com/relevance/rcov) 923 | * コードカバレッジツールです。Ruby 1.9 以降に対応していないため、代わりに[SimpleCov](https://github.com/colszowka/simplecov)を使いましょう。 924 | 925 | 926 | * [therubyracer](https://github.com/cowboyd/therubyracer) 927 | * 莫大にメモリ量を消費するため、本番環境での利用は適当ではありません。 `node.js` を用いた方法をお勧めします。 928 | 929 | この一覧は随時更新していきます。もし有名で問題のある gem をご存知であれば、ご一報頂けると幸いです。 930 | 931 | ## Managing processes 932 | 933 | * 934 | プロジェクトが外部の複数のプロセスに依存している場合、[foreman](https://github.com/ddollar/foreman) を利用しましょう。 935 | [[link](#foreman)] 936 | 937 | # 参考文献 938 | 939 | この文書の他にもRailsのコーディングスタイルについて、優れた文献があります。時間があるときに目を通されてみることをお勧めします: 940 | 941 | * [The Rails 4 Way](http://www.amazon.com/The-Rails-Addison-Wesley-Professional-Ruby/dp/0321944275) 942 | * [Ruby on Rails Guides](http://guides.rubyonrails.org/) 943 | * [The RSpec Book](http://pragprog.com/book/achbd/the-rspec-book) 944 | * [The Cucumber Book](http://pragprog.com/book/hwcuc/the-cucumber-book) 945 | * [Everyday Rails Testing with RSpec](https://leanpub.com/everydayrailsrspec) 946 | * [Better Specs for RSpec](http://betterspecs.org) 947 | 948 | # 貢献 949 | 950 | このガイドに書いてあることはすべて編集可能です。 Railsのコードスタイルに興味のある全ての人と共に取り組むことが私の望みです。 究極的には、全てのRubyコミュニティにとって有益なガイドを作ることができればと思っています。 951 | 遠慮せずチケットを立てたりプルリクエストを送ったりしてください。 952 | また、このプロジェクト(とRubocop)への金銭的な貢献は、[gittip](https://www.gittip.com/bbatsov)経由で行うことができます。 953 | 954 | [![Support via Gittip](https://rawgithub.com/twolfson/gittip-badge/0.2.0/dist/gittip.png)](https://www.gittip.com/bbatsov) 955 | 956 | ## 貢献するには 957 | 958 | 簡単です! [contribution guidelines](https://github.com/bbatsov/rails-style-guide/blob/master/CONTRIBUTING.md) をご覧ください! 959 | 960 | # ライセンス 961 | 962 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png)この著作物は、 [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/deed.en_US)に従います。 963 | 964 | # このガイドを広めてください 965 | 966 | このガイドは有志のコミュニティによって作成されるものです。そもそも存在が世に知られないと、このガイド自体が意味のないものになってしまいます。このページをご覧になった方には、ぜひこのガイドについてTwitterでつぶやいたり、友達や同僚にシェアして、このガイドの存在を広めていただけるようお願いします。 全てのコメント・提案・意見がこのガイドをより良いものにしていきます。 967 | 968 | 親愛をこめて
969 | [Bozhidar](https://twitter.com/bbatsov) 970 | --------------------------------------------------------------------------------