如何打断长长的 Ruby 行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12083011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to break up long lines of Ruby
提问by Matthew
I always get great big lines of code at the top of my Rails models. I am looking for suggestions for the best way to break them up with standard Ruby style. For example, one line I am looking at now is this:
我的 Rails 顶部总是有大量的代码models。我正在寻找用标准 Ruby 风格分解它们的最佳方法的建议。例如,我现在正在看的一行是这样的:
delegate :occupation, :location, :picture_url, :homepage_url, :headline, :full_name, :to => :profile, :prefix => true, :allow_nil => true
What is the conventional style for breaking up these long method call lines?
打破这些长方法调用线的传统风格是什么?
采纳答案by Dave Newton
Something along the lines of:
类似的东西:
delegate :occupation, :location, :picture_url,
:homepage_url, :headline, :full_name,
:to => :profile, :prefix => true, :allow_nil => true
Or if you like to highlight the option hash (a reasonable thing):
或者,如果您想突出显示选项哈希(合理的事情):
delegate :occupation, :location, :picture_url,
:homepage_url, :headline, :full_name,
:to => :profile, :prefix => true, :allow_nil => true
The idea of leaving that all on a single line strikes me as a craptastic idea, it means you have to scroll an arbitrary amount in order to see what's being delegated. Ew.
将所有内容放在一行上的想法在我看来是一个荒谬的想法,这意味着您必须滚动任意数量才能查看被委派的内容。呃。
I'd probably line stuff up a bit, too, maybe alphabetize.
我也可能会排列一些东西,也许是按字母顺序排列。
delegate :full_name, :headline, :homepage_url,
:location, :occupation, :picture_url,
:to => :profile, :prefix => true, :allow_nil => true
If the file didn't have much/any other substantive content, I might put each method symbol on its own line, just to make editing easier. In a larger file, I wouldn't want to take up the space for that.
如果文件没有太多/任何其他实质性内容,我可能会将每个方法符号放在自己的行上,只是为了使编辑更容易。在更大的文件中,我不想占用空间。
Not that I ever think about this kind of stuff.
并不是说我从来没有想过这种事情。
EditI guess I do :/
编辑我想我这样做:/
These days I might group the delegated methods by "similarity", roughly:
这些天我可能会按“相似性”对委托方法进行分组,大致如下:
delegate :full_name, :headline,
:location, :occupation,
:homepage_url, picture_url,
to: :profile, prefix: true, allow_nil: true
My jury's hung on 1.9 hash syntax when the value is also a symbol; I think it looks funny. I'm also not sure where I'd indent it to–might lose it anyway during an IDE reformatting, but I kind of like how it looks above if I'm using the new syntax.
当值也是一个符号时,我的陪审团会坚持使用 1.9 哈希语法;我觉得它看起来很有趣。我也不确定我会把它缩进到哪里——在 IDE 重新格式化期间可能会丢失它,但我有点喜欢它在使用新语法时的外观。
回答by Aldo 'xoen' Giambelluca
The short answer is it depends.
简短的回答是它取决于。
Basics
基本
For a start you can save few chars using the "new" Ruby hash syntax:
首先,您可以使用“新的”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)
Hash/Arrays
散列/数组
Sometimes you need to initialize an array or hash, especially for hashes it's nice to write them this way:
有时你需要初始化一个数组或散列,特别是对于散列,这样写是很好的:
args = {
first_name: "Aldo",
email: "[email protected]",
age: Float::INFINITY
}
The same hash on the same line would be (not as nice):
同一行上的相同哈希将是(不太好):
args = {first_name: "Aldo", email: "[email protected]", age: Float::INFINITY}
Various method calls
各种方法调用
Some methods require many params or these params have long names:
一些方法需要很多参数或者这些参数有很长的名字:
%table
%thead
%th
%td= t("first_name", scope: "activemodel.lazy_model.not_so_active_model", some_interpolation_argument: "Mr.", suffix: "(Jr.)")
In this case I would probably write it this way:
在这种情况下,我可能会这样写:
%table
%thead
%th
%td= t("first_name",
scope: "activemodel.lazy_model.not_so_active_model",
some_interpolation_argument: "Mr.",
suffix: "(Jr.)")
It's still not very beautiful but I guess is less ugly.
它仍然不是很漂亮,但我想不那么难看。
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
Again, not the most beautiful code on earth but It has some kind of structure.
同样,这不是地球上最漂亮的代码,但它具有某种结构。
Also, sometimes you could use variables to split lines. This is just an example, but basicly you name blocks of things (and sometimes after this you realise you can actually move that block in a method)
此外,有时您可以使用变量来分割线。这只是一个示例,但基本上您可以命名事物块(有时在此之后您意识到您实际上可以在方法中移动该块)
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
Blocks
块
Speaking of blocks (closures):
说到块(闭包):
User.all.map { |user| user.method_name }
can be written like this:
可以这样写:
User.all.map(&:method_name)
If you have proper blocks try to use do-end instead of curly braces:
如果您有适当的块,请尝试使用 do-end 而不是花括号:
nicotine_level = User.all.map do |user|
user.smoker? ? (user.age * 12.34) : 0.1234
end
Conditional
有条件的
Don't use the ternary if operator for complex things:
不要将三元 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 you have complex if statements like this:
如果您有这样的复杂 if 语句:
if user.vegetarian? && !user.smoker? && (user.age < 25) && (user.n_girlfriends == 0) && (user.first_name =~ /(A|Z)[0-1]+/)
end
It's probably just better to move things in methods and make things not only shorter but also readable:
最好在方法中移动内容并使内容不仅更短而且可读:
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
Long strings
长字符串
Heredoc is your friend...I always need to google in order to get the syntax right but once you get it right is makes certain things nicer to read:
Heredoc 是你的朋友......我总是需要谷歌以获得正确的语法,但一旦你得到它的正确是使某些事情更容易阅读:
execute <<-SQL
UPDATE people
SET smoker = 0
OK, this is a very bad example.
SQL
Queries
查询
I tend to do this way for simple cases:
对于简单的情况,我倾向于这样做:
# 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
Sometimes queries are even worst. If I use squeeland the query is very big I tend to use parenthesis like this:
有时查询甚至是最糟糕的。如果我使用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
)
)
)
}
I'd say, if possible try to avoid complex queries and split them in smaller scopes or whatever:
我想说,如果可能的话,尽量避免复杂的查询并将它们拆分为更小的范围或其他任何内容:
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)
}
This would be probably the best way.
这可能是最好的方法。
The reality
现实
Unfortunately people tend to write long lines and it's bad:
不幸的是,人们倾向于写长行,这很糟糕:
- Long lines are difficult to read (There is a reason if printed books don't have super-large pages)
- It's true we mostly use 2 screens but when using things like
git difffrom the console having long lines is painful - Sometimes you work on your 13" laptop with less screen estate
- Even if I love to work with 2 screens I like to split my editor to edit 2 files at the same time - long lines force me to use the horizontal scrollbar (most hated thing on earth)
- Yes, you can enable word wrapping in your editor but it's still not as nice (IMHO)
- 长行难以阅读(印刷书籍没有超大页面是有原因的)
- 确实,我们主要使用 2 个屏幕,但是当使用
git diff来自控制台的东西时,排长队很痛苦 - 有时您在屏幕空间较小的 13" 笔记本电脑上工作
- 即使我喜欢使用 2 个屏幕,我也喜欢拆分我的编辑器以同时编辑 2 个文件 - 长行迫使我使用水平滚动条(地球上最讨厌的东西)
- 是的,您可以在编辑器中启用自动换行,但它仍然不那么好(恕我直言)
I have a ruler in my editor so that I know when I'm about to cross the 80th char on the line. But rarely cross the line by few chars it's actually nicer than split it.
我的编辑器中有一个标尺,这样我就知道什么时候我将要越过行上的第 80 个字符。但是很少有几个字符越界它实际上比拆分它更好。
Conclusion
结论
There are several ways of keep lines under the 80s and often depends on the situation. The problem with long lines is not just bad style, long lines are often a symptom of too much complexity.
有几种方法可以将线路保持在 80 年代以下,并且通常取决于情况。长线的问题不仅仅是糟糕的风格,长线往往是过于复杂的症状。
回答by jibiel
Although the question already has two great answers I'd like to refer future readers to the Ruby Style Guidefor such matters.
虽然这个问题已经有两个很好的答案,但我想将这些问题的未来读者推荐给Ruby 风格指南。
Currently the Source Code Layoutsection has plenty of information on how to break lines in various situations:
目前,源代码布局部分有大量关于如何在各种情况下断行的信息:
# 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
And it often turns out to be a ?solution? for overly complex code as @Aldo already have mentioned:
它经常被证明是一个?解决方案?对于@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
回答by alexsanford1
From my experience, it seems like the convention is actually not to break up the lines. Most projects I've seen, including the codebase of rails itself, seem to have no problem with having really long unbroken lines.
根据我的经验,似乎约定实际上并不是为了打破界限。我见过的大多数项目,包括 rails 本身的代码库,似乎都没有问题,有很长的不间断的行。
So I'd say if you want to follow convention, don't break up the lines. If you are determined to break the lines, then there's no widely followed convention for how to do it. You can use whichever coding style that you prefer.
所以我想说如果你想遵循惯例,不要打破界限。如果您决心打破常规,那么就如何做到这一点并没有广泛遵循的惯例。您可以使用您喜欢的任何编码风格。

