Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Ruby Style Guide

License

NotificationsYou must be signed in to change notification settings

airbnb/ruby

This is Airbnb's Ruby Style Guide.

It was inspired byGitHub's guide andRuboCop's guide.

Airbnb also maintains aJavaScript Style Guide.

Table of Contents

  1. Whitespace
    1. Indentation
    2. Inline
    3. Newlines
  2. Line Length
  3. Commenting
    1. File/class-level comments
    2. Function comments
    3. Block and inline comments
    4. Punctuation, spelling, and grammar
    5. TODO comments
    6. Commented-out code
  4. Methods
    1. Method definitions
    2. Method calls
  5. Conditional Expressions
    1. Conditional keywords
    2. Ternary operator
  6. Syntax
  7. Naming
  8. Classes
  9. Exceptions
  10. Collections
  11. Strings
  12. Regular Expressions
  13. Percent Literals
  14. Rails
    1. Scopes
  15. Be Consistent
  16. Translation

Whitespace

Indentation

  • Use soft-tabs with atwo-space indent.[link]

  • Indentwhen as deep ascase.[link]

    casewhensong.name =='Misty'puts'Not again!'whensong.duration >120puts'Too long!'whenTime.now.hour >21puts"It's too late"elsesong.playendkind=caseyearwhen1850..1889then'Blues'when1890..1909then'Ragtime'when1910..1929then'New Orleans Jazz'when1930..1939then'Swing'when1940..1950then'Bebop'else'Jazz'end
  • Align function parameters either all onthe same line or one per line.[link]

    # baddefself.create_translation(phrase_id,phrase_key,target_locale,value,user_id,do_xss_check,allow_verification)  ...end# gooddefself.create_translation(phrase_id,phrase_key,target_locale,value,user_id,do_xss_check,allow_verification)  ...end# gooddefself.create_translation(phrase_id,phrase_key,target_locale,value,user_id,do_xss_check,allow_verification)  ...end
  • Indent succeeding lines in multi-lineboolean expressions.[link]

    # baddefis_eligible?(user)Trebuchet.current.launch?(ProgramEligibilityHelper::PROGRAM_TREBUCHET_FLAG) &&is_in_program?(user) &&program_not_expiredend# gooddefis_eligible?(user)Trebuchet.current.launch?(ProgramEligibilityHelper::PROGRAM_TREBUCHET_FLAG) &&is_in_program?(user) &&program_not_expiredend

Inline

  • Never leave trailing whitespace.[link]

  • When making inline comments, include aspace between the end of the code and the start of your comment.[link]

    # badresult=func(a,b)# we might want to change b to c# goodresult=func(a,b)# we might want to change b to c
  • Use spaces around operators; after commas,colons, and semicolons; and around{ and before}.[link]

    sum=1 +2a,b=1,21 >2 ?true :false;puts'Hi'[1,2,3].each{ |e|putse}
  • Never include a space before a comma.[link]

    result=func(a,b)
  • Do not include space inside blockparameter pipes. Include one space between parameters in a block.Include one space outside block parameter pipes.[link]

    # bad{}.each{ |x,y |putsx}# good{}.each{ |x,y|putsx}
  • Do not leave space between! and itsargument.[link]

    !something
  • No spaces after(,[ or before],).[link]

    some(arg).other[1,2,3].length
  • Omit whitespace when doingstring interpolation.[link]

    # badvar="This#{foobar} is interpolated."# goodvar="This#{foobar} is interpolated."
  • Don't use extra whitespace in rangeliterals.[link]

    # bad(0 ...coll).eachdo |item|# good(0...coll).eachdo |item|

Newlines

  • Add a new line afterif conditions spanningmultiple lines to help differentiate between the conditions and the body.[link]

    if@reservation_alteration.checkin ==@reservation.start_date &&@reservation_alteration.checkout ==(@reservation.start_date +@reservation.nights)redirect_to_alteration@reservation_alterationend
  • Add a new line after conditionals,blocks, case statements, etc.[link]

    ifrobot.is_awesome?send_robot_presentendrobot.add_trait(:human_like_intelligence)
  • Don’t include newlines between areasof different indentation (such as around class or module bodies).[link]

    # badclassFoodefbar# body omittedendend# goodclassFoodefbar# body omittedendend
  • Include one, but no more than one, newline between methods.[link]

    defaenddefbend
  • Use a single empty line to break betweenstatements to break up methods into logical paragraphs internally.[link]

    deftransformorize_carcar=manufacture(options)t=transformer(robot,disguise)car.after_market_mod!t.transform(car)car.assign_cool_name!fleet.add(car)carend
  • End each file with a newline. Don't includemultiple newlines at the end of a file.[link]

Line Length

  • Keep each line of code to a readable length. Unlessyou have a reason not to, keep lines to fewer than 100 characters.(rationale)[link]

Commenting

Though a pain to write, comments are absolutely vital to keeping our codereadable. The following rules describe what you should comment and where. Butremember: while comments are very important, the best code isself-documenting. Giving sensible names to types and variables is much betterthan using obscure names that you must then explain through comments.

When writing your comments, write for your audience: the next contributor whowill need to understand your code. Be generous — the next one may be you!

Google C++ Style Guide

Portions of this section borrow heavily from the GoogleC++ andPython style guides.

File/class-level comments

Every class definition should have an accompanying comment that describes whatit is for and how it should be used.

A file that contains zero classes or more than one class should have a commentat the top describing its contents.

# Automatic conversion of one locale to another where it is possible, like# American to British English.moduleTranslation# Class for converting between text between similar locales.# Right now only conversion between American English -> British, Canadian,# Australian, New Zealand variations is provided.classPrimAndProperdefinitialize@converters={:en=>{:"en-AU"=>AmericanToAustralian.new,:"en-CA"=>AmericanToCanadian.new,:"en-GB"=>AmericanToBritish.new,:"en-NZ"=>AmericanToKiwi.new,}}end  ...# Applies transforms to American English that are common to# variants of all other English colonies.classAmericanToColonial    ...end# Converts American to British English.# In addition to general Colonial English variations, changes "apartment"# to "flat".classAmericanToBritish <AmericanToColonial    ...end

All files, including data and config files, should have file-level comments.

# List of American-to-British spelling variants.## This list is made with# lib/tasks/list_american_to_british_spelling_variants.rake.## It contains words with general spelling variation patterns:#   [trave]led/lled, [real]ize/ise, [flav]or/our, [cent]er/re, plus# and these extras:#   learned/learnt, practices/practises, airplane/aeroplane, ...sectarianizes:sectarianisesneutralization:neutralisation...

Function comments

Every function declaration should have comments immediately preceding it thatdescribe what the function does and how to use it. These comments should bedescriptive ("Opens the file") rather than imperative ("Open the file"); thecomment describes the function, it does not tell the function what to do. Ingeneral, these comments do not describe how the function performs its task.Instead, that should be left to comments interspersed in the function's code.

Every function should mention what the inputs and outputs are, unless it meetsall of the following criteria:

  • not externally visible
  • very short
  • obvious

You may use whatever format you wish. In Ruby, two popular functiondocumentation schemes areTomDoc andYARD. You can alsojust write things out concisely:

# Returns the fallback locales for the_locale.# If opts[:exclude_default] is set, the default locale, which is otherwise# always the last one in the returned list, will be excluded.## For example:#   fallbacks_for(:"pt-BR")#     => [:"pt-BR", :pt, :en]#   fallbacks_for(:"pt-BR", :exclude_default => true)#     => [:"pt-BR", :pt]deffallbacks_for(the_locale,opts={})  ...end

Block and inline comments

The final place to have comments is in tricky parts of the code. If you'regoing to have to explain it at the next code review, you should comment it now.Complicated operations get a few lines of comments before the operationscommence. Non-obvious ones get comments at the end of the line.

deffallbacks_for(the_locale,opts={})# dup() to produce an array that we can mutate.ret=@fallbacks[the_locale].dup# We make two assumptions here:# 1) There is only one default locale (that is, it has no less-specific#    children).# 2) The default locale is just a language. (Like :en, and not :"en-US".)ifopts[:exclude_default] &&ret.last ==default_locale &&ret.last !=language_from_locale(the_locale)ret.popendretend

On the other hand, never describe the code. Assume the person reading the codeknows the language (though not what you're trying to do) better than you do.

Related: do not use block comments. They cannotbe preceded by whitespace and are not as easy to spot as regular comments.[link]

# bad=begincomment lineanother comment line=end# good# comment line# another comment line

Punctuation, spelling and grammar

Pay attention to punctuation, spelling, and grammar; it is easier to readwell-written comments than badly written ones.

Comments should be as readable as narrative text, with proper capitalizationand punctuation. In many cases, complete sentences are more readable thansentence fragments. Shorter comments, such as comments at the end of a line ofcode, can sometimes be less formal, but you should be consistent with yourstyle.

Although it can be frustrating to have a code reviewer point out that you areusing a comma when you should be using a semicolon, it is very important thatsource code maintain a high level of clarity and readability. Properpunctuation, spelling, and grammar help with that goal.

TODO comments

Use TODO comments for code that is temporary, a short-term solution, orgood-enough but not perfect.

TODOs should include the string TODO in all caps, followed by the full nameof the person who can best provide context about the problem referenced by theTODO, in parentheses. A colon is optional. A comment explaining what there isto do is required. The main purpose is to have a consistent TODO format thatcan be searched to find the person who can provide more details upon request.A TODO is not a commitment that the person referenced will fix the problem.Thus when you create a TODO, it is almost always your name that is given.

# bad# TODO(RS): Use proper namespacing for this constant.# bad# TODO(drumm3rz4lyfe): Use proper namespacing for this constant.# good# TODO(Ringo Starr): Use proper namespacing for this constant.

Commented-out code

  • Never leave commented-out code in our codebase.[link]

Methods

Method definitions

  • Usedef with parentheses when there areparameters. Omit the parentheses when the method doesn't accept anyparameters.[link]

    defsome_method# body omittedenddefsome_method_with_parameters(arg1,arg2)# body omittedend
  • Do not use default positional arguments.Use keyword arguments (if available - in Ruby 2.0 or later) or an optionshash instead.[link]

    # baddefobliterate(things,gently=true,except=[],at=Time.now)  ...end# gooddefobliterate(things,gently:true,except:[],at:Time.now)  ...end# gooddefobliterate(things,options={})options={:gently=>true,# obliterate with soft-delete:except=>[],# skip obliterating these things:at=>Time.now,# don't obliterate them until later}.merge(options)  ...end
  • Avoid single-line methods. Althoughthey are somewhat popular in the wild, there are a few peculiarities abouttheir definition syntax that make their use undesirable.[link]

    # baddeftoo_much;something;something_else;end# gooddefsome_method# bodyend

Method calls

Use parentheses for a method call:

  • If the method returns a value.[link]

    # bad@current_user=User.find_by_id1964192# good@current_user=User.find_by_id(1964192)
  • If the first argument to the method usesparentheses.[link]

    # badput!(x +y) %len,value# goodput!((x +y) %len,value)
  • Never put a space between a method name andthe opening parenthesis.[link]

    # badf(3 +2) +1# goodf(3 +2) +1
  • Omit parentheses for a method call if themethod accepts no arguments.[link]

    # badnil?()# goodnil?
  • If the method doesn't return a value (or wedon't care about the return), parentheses are optional. (Especially if thearguments overflow to multiple lines, parentheses may add readability.)[link]

    # okayrender(:partial=>'foo')# okayrender:partial=>'foo'

In either case:

  • If a method accepts an options hash as thelast argument, do not use{} during invocation.[link]

    # badget'/v1/reservations',{:id=>54875}# goodget'/v1/reservations',:id=>54875

Conditional Expressions

Conditional keywords

  • Never usethen for multi-lineif/unless.[link]

    # badifsome_conditionthen  ...end# goodifsome_condition  ...end
  • Never usedo for multi-linewhile oruntil.[link]

    # badwhilex >5do  ...enduntilx >5do  ...end# goodwhilex >5  ...enduntilx >5  ...end
  • Theand,or, andnot keywords are banned. It'sjust not worth it. Always use&&,||, and! instead.[link]

  • Modifierif/unless usage is okay whenthe body is simple, the condition is simple, and the whole thing fits onone line. Otherwise, avoid modifierif/unless.[link]

    # bad - this doesn't fit on one lineadd_trebuchet_experiments_on_page(request_opts[:trebuchet_experiments_on_page])ifrequest_opts[:trebuchet_experiments_on_page] && !request_opts[:trebuchet_experiments_on_page].empty?# okayifrequest_opts[:trebuchet_experiments_on_page] &&     !request_opts[:trebuchet_experiments_on_page].empty?add_trebuchet_experiments_on_page(request_opts[:trebuchet_experiments_on_page])end# bad - this is complex and deserves multiple lines and a commentparts[i]=part.to_i(INTEGER_BASE)if !part.nil? &&[0,2,3].include?(i)# okayreturnifreconciled?
  • Never useunless withelse. Rewritethese with the positive case first.[link]

    # badunlesssuccess?puts'failure'elseputs'success'end# goodifsuccess?puts'success'elseputs'failure'end
  • Avoidunless with multipleconditions.[link]

    # badunlessfoo? &&bar?    ...end# okayif !(foo? &&bar?)    ...end
  • Avoidunless with comparison operators if you can useif with an opposing comparison operator.[link]

    # badunlessx ==10    ...end# goodifx !=10    ...end# badunlessx <10    ...end# goodifx >=10    ...end# okunlessx ===10    ...end
  • Don't use parentheses around thecondition of anif/unless/while.[link]

    # badif(x >10)  ...end# goodifx >10  ...end

Ternary operator

  • Avoid the ternary operator (?:) exceptin cases where all expressions are extremely trivial. However, do use theternary operator(?:) overif/then/else/end constructs for single lineconditionals.[link]

    # badresult=ifsome_conditionthensomethingelsesomething_elseend# goodresult=some_condition ?something :something_else
  • Use one expression per branch in a ternaryoperator. This also means that ternary operators must not be nested. Preferif/else constructs in these cases.[link]

    # badsome_condition ?(nested_condition ?nested_something :nested_something_else) :something_else# goodifsome_conditionnested_condition ?nested_something :nested_something_elseelsesomething_elseend
  • Avoid multiple conditions in ternaries.Ternaries are best used with single conditions.[link]

  • Avoid multi-line?: (the ternaryoperator), useif/then/else/end instead.[link]

    # badsome_really_long_condition_that_might_make_you_want_to_split_lines ?something :something_else# goodifsome_really_long_condition_that_might_make_you_want_to_split_linessomethingelsesomething_elseend

Nested conditionals

  • Avoid the use of nested conditionals for flow of control.(More on this.)[link]

    Prefer a guard clause when you can assert invalid data. A guard clauseis a conditional statement at the top of a function that returns as soonas it can.

    The general principles boil down to:

    • Return immediately once you know your function cannot do anything more.
    • Reduce nesting and indentation in the code by returning early. This makesthe code easier to read and requires less mental bookkeeping on the partof the reader to keep track ofelse branches.
    • The core or most important flows should be the least indented.
    # baddefcomputeserver=find_serverifserverclient=server.clientifclientrequest=client.make_requestifrequestprocess_request(request)endendendend# gooddefcomputeserver=find_serverreturnunlessserverclient=server.clientreturnunlessclientrequest=client.make_requestreturnunlessrequestprocess_request(request)end

    Prefernext in loops instead of conditional blocks.

    # bad[0,1,2,3].eachdo |item|ifitem >1putsitemendend# good[0,1,2,3].eachdo |item|nextunlessitem >1putsitemend

    See also the section "Guard Clause", p68-70 in Beck, Kent.Implementation Patterns. Upper Saddle River: Addison-Wesley, 2008, whichhas inspired some of the content above.

Syntax

  • Never usefor, unless you know exactly why. Most of thetime iterators should be used instead.for is implemented in terms ofeach (so you're adding a level of indirection), but with a twist -fordoesn't introduce a new scope (unlikeeach) and variables defined in itsblock will be visible outside it.[link]

    arr=[1,2,3]# badforeleminarrdoputselemend# goodarr.each{ |elem|putselem}
  • Prefer{...} overdo...end forsingle-line blocks. Avoid using{...} for multi-line blocks (multilinechaining is always ugly). Always usedo...end for "control flow" and"method definitions" (e.g. in Rakefiles and certain DSLs). Avoiddo...endwhen chaining.[link]

    names=["Bozhidar","Steve","Sarah"]# goodnames.each{ |name|putsname}# badnames.eachdo |name|putsnameend# goodnames.eachdo |name|putsnameputs'yay!'end# badnames.each{ |name|putsnameputs'yay!'}# goodnames.select{ |name|name.start_with?("S")}.map{ |name|name.upcase}# badnames.selectdo |name|name.start_with?("S")end.map{ |name|name.upcase}

    Some will argue that multiline chaining would look okay with the use of{...}, but they should ask themselves if this code is really readable andwhether the block's content can be extracted into nifty methods.

  • Use shorthand self assignment operatorswhenever applicable.[link]

    # badx=x +yx=x *yx=x**yx=x /yx=x ||yx=x &&y# goodx +=yx *=yx **=yx /=yx ||=yx &&=y
  • Avoid semicolons except for in single line classdefinitions. When it is appropriate to use a semicolon, it should bedirectly adjacent to the statement it terminates: there should be nospace before the semicolon.[link]

    # badputs'foobar';# superfluous semicolonputs'foo';puts'bar'# two expressions on the same line# goodputs'foobar'puts'foo'puts'bar'puts'foo','bar'# this applies to puts in particular
  • Use :: only to reference constants(this includesclasses and modules) and constructors (like Array() or Nokogiri::HTML()).Do not use :: for regular method invocation.[link]

    # badSomeClass::some_methodsome_object::some_method# goodSomeClass.some_methodsome_object.some_methodSomeModule::SomeClass::SOME_CONSTSomeModule::SomeClass()
  • Avoidreturn where not required.[link]

    # baddefsome_method(some_arr)returnsome_arr.sizeend# gooddefsome_method(some_arr)some_arr.sizeend
  • Don't use the return value of= inconditionals[link]

    # bad - shows intended use of assignmentif(v=array.grep(/foo/))  ...end# badifv=array.grep(/foo/)  ...end# goodv=array.grep(/foo/)ifv  ...end
  • Use||= freely to initialize variables.[link]

    # set name to Bozhidar, only if it's nil or falsename ||='Bozhidar'
  • Don't use||= to initialize booleanvariables. (Consider what would happen if the current value happened to befalse.)[link]

    # bad - would set enabled to true even if it was falseenabled ||=true# goodenabled=trueifenabled.nil?
  • Use.call explicitly when calling lambdas.[link]

    # badlambda.(x,y)# goodlambda.call(x,y)
  • Avoid using Perl-style special variables (like$0-9,$, etc. ). They are quite cryptic and their use in anything butone-liner scripts is discouraged. Prefer long form versions such as$PROGRAM_NAME.[link]

  • When a method block takes only oneargument, and the body consists solely of reading an attribute or callingone method with no arguments, use the&: shorthand.[link]

    # badbluths.map{ |bluth|bluth.occupation}bluths.select{ |bluth|bluth.blue_self?}# goodbluths.map(&:occupation)bluths.select(&:blue_self?)
  • Prefersome_method overself.some_method whencalling a method on the current instance.[link]

    # baddefend_dateself.start_date +self.nightsend# gooddefend_datestart_date +nightsend

    In the following three common cases,self. is required by the languageand is good to use:

    1. When defining a class method:def self.some_method.
    2. Theleft hand side when calling an assignment method, including assigningan attribute whenself is an ActiveRecord model:self.guest = user.
    3. Referencing the current instance's class:self.class.
  • When defining an object of any mutabletype meant to be a constant, make sure to callfreeze on it. Commonexamples are strings, arrays, and hashes.(More on this.)[link]

    The reason is that Ruby constants are actually mutable. Callingfreezeensures they are not mutated and are therefore truly constant andattempting to modify them will raise an exception. For strings, this allowsolder versions of Ruby below 2.2 to intern them.

    # badclassColorRED='red'BLUE='blue'GREEN='green'ALL_COLORS=[RED,BLUE,GREEN,]COLOR_TO_RGB={RED=>0xFF0000,BLUE=>0x0000FF,GREEN=>0x00FF00,}end# goodclassColorRED='red'.freezeBLUE='blue'.freezeGREEN='green'.freezeALL_COLORS=[RED,BLUE,GREEN,].freezeCOLOR_TO_RGB={RED=>0xFF0000,BLUE=>0x0000FF,GREEN=>0x00FF00,}.freezeend

Naming

  • Usesnake_case for methods and variables.[link]

  • UseCamelCase for classes and modules. (Keepacronyms like HTTP, RFC, XML uppercase.)[link]

  • UseSCREAMING_SNAKE_CASE for otherconstants.[link]

  • The names of predicate methods (methodsthat return a boolean value) should end in a question mark.(i.e.Array#empty?).[link]

  • The names of potentially "dangerous" methods(i.e. methods that modifyself or the arguments,exit!, etc.) shouldend with an exclamation mark. Bang methods should only exist if a non-bangmethod exists. (More on this.)[link]

  • Name throwaway variables_.[link]

    version='3.2.1'major_version,minor_version,_=version.split('.')

Classes

  • Avoid the usage of class (@@) variablesdue to their "nasty" behavior in inheritance.[link]

    classParent@@class_var='parent'defself.print_class_varputs@@class_varendendclassChild <Parent@@class_var='child'endParent.print_class_var# => will print "child"

    As you can see all the classes in a class hierarchy actually share oneclass variable. Class instance variables should usually be preferredover class variables.

  • Usedef self.method to define singletonmethods. This makes the methods more resistant to refactoring changes.[link]

    classTestClass# baddefTestClass.some_method    ...end# gooddefself.some_other_method    ...end
  • Avoidclass << self except when necessary,e.g. single accessors and aliased attributes.[link]

    classTestClass# badclass <<selfdeffirst_method      ...enddefsecond_method_etc      ...endend# goodclass <<selfattr_accessor:per_pagealias_method:nwo,:find_by_name_with_ownerenddefself.first_method    ...enddefself.second_method_etc    ...endend
  • Indent thepublic,protected, andprivate methods as much the method definitions they apply to. Leave oneblank line above and below them.[link]

    classSomeClassdefpublic_method# ...endprivatedefprivate_method# ...endend

Exceptions

  • Don't use exceptions for flow of control.[link]

    # badbeginn /drescueZeroDivisionErrorputs"Cannot divide by 0!"end# goodifd.zero?puts"Cannot divide by 0!"elsen /dend
  • Avoid rescuing theException class.[link]

    # badbegin# an exception occurs hererescueException# exception handlingend# goodbegin# an exception occurs hererescueStandardError# exception handlingend# acceptablebegin# an exception occurs hererescue# exception handlingend
  • Don't specifyRuntimeError explicitly inthe two argument version of raise. Prefer error sub-classes for clarity andexplicit error creation.[link]

    # badraiseRuntimeError,'message'# better - RuntimeError is implicit hereraise'message'# bestclassMyExplicitError <RuntimeError;endraiseMyExplicitError
  • Prefer supplying an exception class and a message as two separate argumentstoraise, instead of an exception instance.[link]

    # badraiseSomeException.new('message')# Note that there is no way to do `raise SomeException.new('message'), backtrace`.# goodraiseSomeException,'message'# Consistent with `raise SomeException, 'message', backtrace`.
  • Avoid using rescue in its modifier form.[link]

    # badread_filerescuehandle_error($!)# goodbeginread_filerescueErrno:ENOENT=>exhandle_error(ex)end

Collections

  • Prefermap overcollect.[link]

  • Preferdetect overfind. The use offindis ambiguous with regard to ActiveRecord'sfind method -detect makesclear that you're working with a Ruby collection, not an AR object.[link]

  • Preferreduce overinject.[link]

  • Prefersize over eitherlength orcountfor performance reasons.[link]

  • Prefer literal array and hash creationnotation unless you need to pass parameters to their constructors.[link]

    # badarr=Array.newhash=Hash.new# goodarr=[]hash={}# good because constructor requires parametersx=Hash.new{ |h,k|h[k]={}}
  • FavorArray#join overArray#* for clarity.[link]

    # bad%w(onetwothree) *', '# => 'one, two, three'# good%w(onetwothree).join(', ')# => 'one, two, three'
  • Use symbols instead of strings as hash keys.[link]

    # badhash={'one'=>1,'two'=>2,'three'=>3}# goodhash={:one=>1,:two=>2,:three=>3}
  • Relatedly, use plain symbols instead of stringsymbols when possible.[link]

    # bad:"symbol"# good:symbol
  • UseHash#key? instead ofHash#has_key? andHash#value? instead ofHash#has_value?. Accordingto Matz, the longer forms are considered deprecated.[link]

    # badhash.has_key?(:test)hash.has_value?(value)# goodhash.key?(:test)hash.value?(value)
  • Use multi-line hashes when it makes the codemore readable, and use trailing commas to ensure that parameter changesdon't cause extraneous diff lines when the logic has not otherwise changed.[link]

    hash={:protocol=>'https',:only_path=>false,:controller=>:users,:action=>:set_password,:redirect=>@redirect_url,:secret=>@secret,}
  • Use a trailing comma in anArray thatspans more than 1 line[link]

    # goodarray=[1,2,3]# goodarray=["car","bear","plane","zoo",]

Strings

  • Prefer string interpolation instead ofstring concatenation:[link]

    # bademail_with_name=user.name +' <' +user.email +'>'# goodemail_with_name="#{user.name} <#{user.email}>"

    Furthermore, keep in mind Ruby 1.9-style interpolation. Let's say you arecomposing cache keys like this:

    CACHE_KEY='_store'cache.write(@user.id +CACHE_KEY)

    Prefer string interpolation instead of string concatenation:

    CACHE_KEY='%d_store'cache.write(CACHE_KEY %@user.id)
  • Avoid usingString#+ when you need toconstruct large data chunks. Instead, useString#<<. Concatenation mutatesthe string instance in-place and is always faster thanString#+, whichcreates a bunch of new string objects.[link]

    # good and also faststory=''story <<'The Ugly Duckling'paragraphs.eachdo |paragraph|story <<paragraphend
  • Use\ at the end of the line instead of+or<< to concatenate multi-line strings.[link]

    # bad"Some string is really long and " +"spans multiple lines.""Some string is really long and " <<"spans multiple lines."# good"Some string is really long and " \"spans multiple lines."

Regular Expressions

  • Avoid using$1-9 as it can be hard to trackwhat they contain. Named groups can be used instead.[link]

    # bad/(regexp)/ =~string...process $1# good/(?<meaningful_var>regexp)/ =~string...processmeaningful_var
  • Be careful with^ and$ as theymatch start/end of line, not string endings. If you want to match the wholestring use:\A and\z.[link]

    string="some injection\nusername"string[/^username$/]# matchesstring[/\Ausername\z/]# don't match
  • Usex modifier for complex regexps. This makesthem more readable and you can add some useful comments. Just be careful asspaces are ignored.[link]

    regexp=%r{  start         # some text\s            # white space char  (group)       # first group  (?:alt1|alt2) # some alternation  end}x

Percent Literals

  • Prefer parentheses over curlybraces, brackets, or pipes when using%-literal delimiters forconsistency, and because the behavior of%-literals is closer to methodcalls than the alternatives.[link]

    # bad%w[datelocale]%w{datelocale}%w|datelocale|# good%w(datelocale)
  • Use%w freely.[link]

    STATES=%w(draftopenclosed)
  • Use%() for single-line strings which requireboth interpolation and embedded double-quotes. For multi-line strings,prefer heredocs.[link]

    # bad - no interpolation needed%(Welcome, Jane!)# should be 'Welcome, Jane!'# bad - no double-quotes%(This is#{quality} style)# should be "This is #{quality} style"# bad - multiple lines%(Welcome, Jane!\nPlease enjoy your stay at#{location}\nCheers!)# should be a heredoc.# good - requires interpolation, has quotes, single line%(Welcome,#{name}!)
  • Use%r only for regular expressions matchingmorethan one '/' character.[link]

    # bad%r(\s+)# still bad%r(^/(.*)$)# should be /^\/(.*)$/# good%r(^/blog/2011/(.*)$)
  • Avoid the use of %x unless you're going to invoke acommand with backquotes in it (which is rather unlikely).[link]

    # baddate=%x(date)# gooddate=`date`echo=%x(echo `date`)

Rails

  • When immediately returning after callingrender orredirect_to, putreturn on the next line, not the same line.[link]

    # badrender:text=>'Howdy'andreturn# goodrender:text=>'Howdy'return# still badrender:text=>'Howdy'andreturniffoo.present?# goodiffoo.present?render:text=>'Howdy'returnend

Scopes

  • When defining ActiveRecord model scopes, wrap therelation in alambda. A naked relation forces a database connection to beestablished at class load time (instance startup).[link]

    # badscope:foo,where(:bar=>1)# goodscope:foo,->{where(:bar=>1)}

Be Consistent

If you're editing code, take a few minutes to look at the code around you anddetermine its style. If they use spaces around all their arithmeticoperators, you should too. If their comments have little boxes of hash marksaround them, make your comments have little boxes of hash marks around themtoo.

The point of having style guidelines is to have a common vocabulary of codingso people can concentrate on what you're saying rather than on how you'resaying it. We present global style rules here so people know the vocabulary,but local style is also important. If code you add to a file looksdrastically different from the existing code around it, it throws readers outof their rhythm when they go to read it. Avoid this.

Google C++ Style Guide

Translation

This style guide is also available in other languages:

About

Ruby Style Guide

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors43

Languages


[8]ページ先頭

©2009-2025 Movatter.jp