├── 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 | [](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 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 | [](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 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 |
--------------------------------------------------------------------------------