- Ruby / Rails関連
READ MORE
こんにちは、hachi8833です。
今回から趣向を変えて、弊社筆頭プログラマーのbabaさんによる社内講義録を元に記事を書きます。第一回は「Railsらしく書こう」です。
特にプログラミング経験の浅いうちは、コーディングに関するさまざまな慣習を知らないがために遠回りをしてしまうことがあります。この講義では、Rails (とRuby) の基本的なコーディングルールについて説明します。
なお、この講義はRails3時代のものを元にしていますのでご了承ください。
class CommentsController<ApplicationController
def index()
@comment=Comment.find ( params[:id] )
if(request.format==:xml) then
render(:layout=>false)
end
end
end
上のコーディングスタイルには問題があります。どこがRails/Rubyの慣習に反しているでしょうか?
<
の前後にスペースがない=
の前後にスペースがないfind
メソッド後の丸かっこ(
の前後にスペースがある==
の前後にスペースがないthen
は不要()
は不要=>
の前後にスペースがない()
は不要細かい点には異論もあるかと思いますが、特にチームで開発する場合にはチーム内でコーディングスタイルを揃えるのが原則です。
以前はインデントをタブにするかスペースにするかという議論が多かったようですが、近年はHTML表示からのコピペで不具合の生じにくく、エディタによってインデント量の変わらない、スペースでのインデントが優勢です。私自身、以前はタブ派でしたがこの機会にスペースインデントに宗旨変えしました。
上記の問題を以下の慣習に合わせて修正したものを示します。
()
間にはスペースを置かない()
は使わないclass CommentsController < ApplicationController
def index
@comment = Comment.find(params[:id])
if request.format == :xml
render :layout => false
end
end
end
その他にこんな慣習もあります。
private
やprotected
の後には1段インデントを置く{ key: :value }
スタイルにする (以前はロケット演算子 =>
を使用した { :key => :value }
という記法)and
やor
よりも&&
と||
を使用するself.メソッド名
よりもクラス名 << self
を使用する{}
でブロックを表すときは { do_something }
のように内側にもスペースを置く
出典: Railsのコーディングスタイル
rollとroleの取り違えなど、スペルミスは意外と発生しやすいものです。不安であれは辞書で確認するようにしてください。
クラス名・メソッド名・変数名は、英単語を複合させて命名するのが普通ですが、ここにも慣習があります。
大文字小文字の表記法であるキャメルケースとスネークケースについて説明します。キャメルケースは「CamelCase」のように単語間のスペースがなく、単語が大文字で始まる表記法です。その中でも、先頭の単語も大文字で始まるものをアッパーキャメルケースと呼びます。スネークケースは「snake_case」のように単語を小文字にしてアンダースコアでつなぐ表記法です。
次にRubyとRailsの慣習を以下に示します。
MyClass
update_attribute
@user_name
メソッド名の命名に使う語彙にも慣習があります。
プロパティ的なメソッドには動詞を含めず、名詞のみにする
def width
def width=(val)
def get_width
def get_width=(val)
.get_width
としなくても.width
だけで十分意味が通じるという考え方です。
以下はよく知られた慣習だと思います。
true
/false
を返すメソッド名の末尾には?
を付けます。例: valid?
!
を付けます。例: save!
前者は意味を限定して明確にし、後者は使用上の注意が必要であることを知らせます。
Railsでは、コントローラ名は英語の複数形で終わり、モデル名は英語の単数形で終わることが前提となっています。また、コントローラ名とモデル名が互いに関連する場合には原則として一貫した命名をする慣習があります。
たとえば、ユーザープロファイルを扱うコントローラとモデルを作成する場合、コントローラ名はUserProfiles、モデル名はUserProfileとします。
#コントローラ
class UserProfiles < ApplicationController
end
#モデル
class UserProfile < ActiveRecord::Base
end
コントローラ名とモデル名はどちらもクラス名なのでキャメルケースで表記しますが、それぞれが保存されるファイルの名前はスネークケースで記述しますので注意してください。
なお、モデルと関連付けられるデータベースのテーブル名は「複数形かつスネークケース」となります。
rails generateコマンドでファイルを生成すればファイル名設定は自動的に行なってくれます。
rails generate controller UserProfiles
rails generate model UserProfile
コントローラ名やモデル名を決める時も、スペルが不安な場合はirbなどで確認しましょう。
rb -r active_support/all
irb(main):001:0> 'user_profiles'.classify
=> "UserProfile"
なお、personの複数形はActiveSupportではpersonsではなく「people」だったりなんかします。これは罠になりえますね。
rb -r active_support/all
irb(main):001:0>'my_people'.classify
=> "MyPerson"
このあたりを操作できる便利メソッドもご紹介します。
singularize
: 単数形にするpluralize
: 複数形にするcamelize
: キャメルケースにするunderscore
: アンダースコア形式(スネークケース)にするtableize
: テーブル名にする(pluralize + underscore)classify
: モデル名にする(singularize + camerize)constantize
: その名前の定数にするメソッド名の命名にはうんと気を遣いましょう。メソッド名を見るだけで目的と用途が一目瞭然になるのが理想です。これができるようになると、他のメンバーも未来の自分も助かります。
コードに付けるコメントは最小限にしましょう。余分なコメントがなくても楽に読めるコードを書く(よく言われることですが「ソースコードに語らせる」)ように心がけます。逆に言えば、コードのまずさを補おうとしてコメントを増やすのは最悪です。
コメントは、方法を説明するためではなく理由・目的を説明するようにします。方法はコードが語っているのでコメントで説明する必要はないはずです。
メソッドはなるべくコンパクトになるように心がけましょう。メソッドが大きくなるようならリファクタリングします。
Rubyの強力な機能であるenumerableを積極的に使いましょう。Rubyでは、forやwhileなどはenumerableで書く方が簡潔になります。特にmap
がおすすめです。
each
all?
, any?
, select
, collect
, detect
, reject
, map
, inject
Ruby on Railsという名前からもわかるように、フレームワークを使用する場合には独自の実装よりも既存のレールに乗っているものを極力活用するようにしましょう。そのためには:
コントローラやビューが散らからないように、コード量を増やさないように心がけましょう。よく使うコードはlibやhelperにまとめておくとよいでしょう。
ネットなどで見かける古い情報の扱いには注意が必要です。
ライブラリには、ライブラリ同士の相性や、バージョン依存の問題が生じることがしばしばあります。ライブラリ導入の際にはREADMEをよく読み、テストを書いて実行するようにしてください。
最近だとRMagickとImageMagickのバージョンの問題が有名です。
さてここで宣伝です。今月12月25日19:15より、弊社オフィスにてbabaさん主催の勉強会「良い設計、悪い設計について議論する会」を無料にて開催いたします。どなたでもご参加いただけます。
詳細についてはatnd.orgのエントリを参照してください。