简短的回答是视情况而定。
基础知识
首先,您可以使用“新”Ruby 哈希语法保存几个字符:
result = very_long_method_name(something: 1, user: user, flange_factor: 1.34)
对比
result = very_long_method_name(:something => 1, :user => user, :flange_factor => 1.34)
哈希/数组
有时您需要初始化一个数组或散列,尤其是对于散列,最好这样写:
args = {
first_name: "Aldo",
email: "nospam@mail.example.com",
age: Float::INFINITY
}
同一行上的相同哈希将是(不那么好):
args = {first_name: "Aldo", email: "nospam@mail.example.com", 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
有条件的
不要将三元 if 运算符用于复杂的事情:
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
长字符串
Heredoc 是你的朋友...我总是需要在谷歌上搜索以获取正确的语法,但一旦你做对了,某些内容会更易于阅读:
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)
}
这可能是最好的方法。
现实
不幸的是,人们倾向于写长行,这很糟糕:
- 排长队难以阅读(印刷书籍没有超大页面是有原因的)
- 确实,我们主要使用 2 个屏幕,但是当从控制台使用
git diff 之类的东西时,排长队很痛苦
- 有时您使用屏幕空间较小的 13 英寸笔记本电脑工作
- 即使我喜欢使用 2 个屏幕,我也喜欢拆分我的编辑器来同时编辑 2 个文件 - 长行迫使我使用水平滚动条(地球上最讨厌的东西)
- 是的,您可以在编辑器中启用自动换行,但效果仍然不理想(恕我直言)
我的编辑器中有一把尺子,这样我就知道何时要越过该行的第 80 个字符。
但很少通过几个字符越界,这实际上比拆分更好。
结论
在 80 年代以下有几种保持线路的方法,并且通常取决于具体情况。
长线的问题不仅仅是风格不好,长线通常是过于复杂的症状。