Rails models
の上部に、常に大きな大きなコード行が表示されます。標準Rubyスタイルでそれらを分割する最良の方法の提案を探しています。たとえば、私が今見ている1行は次のとおりです。
delegate :occupation, :location, :picture_url, :homepage_url, :headline, :full_name, :to => :profile, :prefix => true, :allow_nil => true
これらの長いメソッド呼び出し行を分割するための従来のスタイルは何ですか?
以下の線に沿ったもの:
delegate :occupation, :location, :picture_url,
:homepage_url, :headline, :full_name,
:to => :profile, :prefix => true, :allow_nil => true
または、オプションハッシュを強調表示する場合(合理的なこと):
delegate :occupation, :location, :picture_url,
:homepage_url, :headline, :full_name,
:to => :profile, :prefix => true, :allow_nil => true
それをすべて1行に残すという考えは、ひどい考えだと思います。つまり、委任されているものを見るには、任意の量をスクロールする必要があるということです。えー.
私もおそらく少し並べて、多分アルファベット順にします。
delegate :full_name, :headline, :homepage_url,
:location, :occupation, :picture_url,
:to => :profile, :prefix => true, :allow_nil => true
ファイルにその他の実質的なコンテンツがあまりない場合は、編集を簡単にするために、各メソッドシンボルをそれぞれの行に配置します。大きなファイルでは、そのためのスペースを取りたくありません。
この種のことを考えたことはありません。
編集私はそう思う:/
最近では、委任されたメソッドを「類似性」によって大まかにグループ化できます。
delegate :full_name, :headline,
:location, :occupation,
:homepage_url, picture_url,
to: :profile, prefix: true, allow_nil: true
私のsymbol審員は、値がシンボルでもある場合、1.9ハッシュ構文に依存しています。面白そうだと思います。インデントする場所もわかりません。IDE再フォーマット中に失われる可能性がありますが、新しい構文を使用している場合は上記のように見えます。
短い答えはitに依存します。
はじめに、 "new" Rubyハッシュ構文を使用して、いくつかの文字を保存できます。
result = very_long_method_name(something: 1, user: user, flange_factor: 1.34)
vs.
result = very_long_method_name(:something => 1, :user => user, :flange_factor => 1.34)
配列またはハッシュを初期化する必要がある場合があります。特にハッシュの場合は、次のように記述するのが良いでしょう。
args = {
first_name: "Aldo",
email: "[email protected]",
age: Float::INFINITY
}
同じ行の同じハッシュは次のようになります(ニースではありません):
args = {first_name: "Aldo", email: "[email protected]", age: Float::INFINITY}
いくつかのメソッドは多くのパラメーターを必要とするか、これらのパラメーターは長い名前を持っています:
%table
%thead
%th
%td= t("first_name", scope: "activemodel.lazy_model.not_so_active_model", some_interpolation_argument: "Mr.", suffix: "(Jr.)")
この場合、おそらく次のように記述します。
%table
%thead
%th
%td= t("first_name",
scope: "activemodel.lazy_model.not_so_active_model",
some_interpolation_argument: "Mr.",
suffix: "(Jr.)")
それはまだあまり美しくはありませんが、私はあまりくないと思います。
class person < ActiveRecord::Base
validates :n_cars, numericality: {
only_integer: true,
greater_than: 2,
odd: true,
message: t("greater_than_2_and_odd",
scope: "activerecord.errors.messages")
}
end
繰り返しますが、地球上で最も美しいコードではありませんが、何らかの構造を持っています。
また、変数を使用して行を分割することもできます。これは単なる例にすぎませんが、基本的には物事のブロックに名前を付けます(そして、この後、メソッド内でそのブロックを実際に移動できることに気付くことがあります)
class person < ActiveRecord::Base
NUMERICALITY_OPTS = {
only_integer: true,
greater_than: 2,
odd: true,
message: t("greater_than_2_and_odd", scope: "activerecord.errors.messages")
}
validates :n_cars, numericality: NUMERICALITY_OPTS
end
ブロック(クロージャー)といえば:
User.all.map { |user| user.method_name }
このように書くことができます:
User.all.map(&:method_name)
適切なブロックがある場合は、中括弧ではなくdo-endを使用してください。
nicotine_level = User.all.map do |user|
user.smoker? ? (user.age * 12.34) : 0.1234
end
複雑なものに三項演算子を使用しないでください。
nicotine_level = user.smoker? ? (user.age * 1.234 + user.other_method) : ((user.age - 123 + user.flange_factor) * 0)
if user.smoker?
nicotine_level = user.age * 1.234 + user.other_method
else
nicotine_level = (user.age - 123 + user.flange_factor) * 0
end
このような複雑なifステートメントがある場合:
if user.vegetarian? && !user.smoker? && (user.age < 25) && (user.n_girlfriends == 0) && (user.first_name =~ /(A|Z)[0-1]+/)
end
メソッドで物事を移動し、物事を短くするだけでなく読みやすくすることはおそらく良いでしょう:
if user.healthy? && user.has_a_weird_name?
# Do something
end
# in User
def healthy?
vegetarian? && !smoker? && (age < 25) && (n_girlfriends == 0)
end
def user.has_a_weird_name?
user.first_name =~ /(A|Z)[0-1]+/
end
ヒアドックはあなたの友人です...構文を正しくするためには常にグーグルで検索する必要がありますが、一度正しいと特定の事が読みやすくなります:
execute <<-SQL
UPDATE people
SET smoker = 0
OK, this is a very bad example.
SQL
私は単純な場合にこの方法を使用する傾向があります。
# Totally random example, it's just to give you an idea
def cars_older_than_n_days(days)
Car.select("cars.*, DATEDIFF(NOW(), release_date) AS age")
.joins(:brand)
.where(brand: {country: "German"})
.having("age > ?", days)
end
クエリが最悪の場合もあります。 squeel を使用し、クエリが非常に大きい場合、次のように括弧を使用する傾向があります。
# Again, non-sense query
Person.where {
first_name = "Aldo" |
last_name = "McFlange" |
(
age = "18" &
first_name = "Mike" &
email =~ "%@hotmail.co.uk"
) |
(
person.n_girlfriends > 1 &
(
country = "Italy" |
salary > 1_234_567 |
very_beautiful = true |
(
whatever > 123 &
you_get_the_idea = true
)
)
)
}
可能であれば、複雑なクエリを避けて、より小さなスコープなどに分割するようにしてください。
scope :healthy_users, lambda {
younger_than(25).
without_car.
non_smoking.
no_girlfriend
}
scope :younger_than, lambda { |age|
where("users.age < ?", age)
}
scope :without_car, lambda {
where(car_id: nil)
}
scope :non_smoking, lambda {
where(smoker: false)
}
scope :no_girlfriend, lambda {
where(n_girlfriends: 0)
}
これがおそらく最良の方法でしょう。
残念ながら、人々は長い行を書く傾向があり、それは悪いです:
git diff
長い行を持つコンソールからの痛みエディターにルーラーがあるので、行の80番目の文字を越えようとしていることがわかります。しかし、いくつかの文字で行を越えることはめったにありません。実際には分割するよりも優れています。
80年代にラインを維持する方法はいくつかあり、状況によって異なります。長い行の問題は、スタイルが悪いだけではありません。長い行は、多くの場合、複雑すぎます。
質問にはすでに2つの素晴らしい答えがありますが、将来の読者にはこのような問題について Ruby Style Guide を参照したいと思います。
現在、 ソースコードレイアウト セクションには、さまざまな状況で行を分割する方法に関する多くの情報があります。
# starting point (line is too long)
def send_mail(source)
Mailer.deliver(to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text)
end
# bad (double indent)
def send_mail(source)
Mailer.deliver(
to: '[email protected]',
from: '[email protected]',
subject: 'Important message',
body: source.text)
end
# good
def send_mail(source)
Mailer.deliver(to: '[email protected]',
from: '[email protected]',
subject: 'Important message',
body: source.text)
end
# good (normal indent)
def send_mail(source)
Mailer.deliver(
to: '[email protected]',
from: '[email protected]',
subject: 'Important message',
body: source.text
)
end
# bad - need to consult first line to understand second line
one.two.three.
four
# good - it's immediately clear what's going on the second line
one.two.three
.four
そして、@ Aldoがすでに述べたように、非常に複雑なコードの"解決策"であることがよくあります。
# bad
some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
# good
if some_condition
nested_condition ? nested_something : nested_something_else
else
something_else
end
私の経験から、慣習は実際に行を分割することではないようです。 Rails自体のコードベースを含む、私が見たほとんどのプロジェクトは、途切れのない長い行を持つことに何の問題もないようです。
ですから、慣習に従うことを望むなら、行を分割しないでください。行を分割することに決めた場合、その方法について広く採用されている規則はありません。好みのコーディングスタイルを使用できます。