Skip to content

ruby-ve/ruby

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Repository files navigation

Ruby Style Guide

This is Airbnb's Ruby Style Guide.

It was inspired by Github's guide and Bozhidar Batsov's guide.

Airbnb also maintains a JavaScript Style Guide.

Table of Contents

  1. Whitespace 1. Indentation 1. Inline 1. Newlines
  2. Line Length
  3. Commenting 1. File/class-level comments 1. Function comments 1. Block and inline comments 1. Punctuation, spelling, and grammar 1. TODO comments 1. Commented-out code
  4. Methods 1. Method definitions 1. Method calls
  5. Conditional Expressions 1. Conditional keywords 1. 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 a two space-indent.[link]

  • Indent when as deep as case. [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 on the 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-line boolean 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 a space 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 block parameter 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 its argument.[link]

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

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

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

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

Newlines

  • Add a new line after if conditions span multiple 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 areas of different indentation (such as around class or module bodies). [link]

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

    defaenddefbend
  • Use a single empty line to break between statements 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 include multiple newlines at the end of a file. [link]

Line Length

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

Commenting

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

When writing your comments, write for your audience: the next contributor who will 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 Google C++ and Python style guides.

File/class-level comments

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

A file that contains zero classes or more than one class should have a comment at 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 that describe what the function does and how to use it. These comments should be descriptive ("Opens the file") rather than imperative ("Open the file"); the comment describes the function, it does not tell the function what to do. In general, 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 meets all of the following criteria:

  • not externally visible
  • very short
  • obvious

You may use whatever format you wish. In Ruby, two popular function documentation schemes are TomDoc and YARD. You can also just 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're going 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 operations commence. 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 code knows the language (though not what you're trying to do) better than you do.

Related: do not use block comments. They cannot be 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 read well-written comments than badly written ones.

Comments should be as readable as narrative text, with proper capitalization and punctuation. In many cases, complete sentences are more readable than sentence fragments. Shorter comments, such as comments at the end of a line of code, can sometimes be less formal, but you should be consistent with your style.

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

TODO comments

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

TODOs should include the string TODO in all caps, followed by the full name of the person who can best provide context about the problem referenced by the TODO, in parentheses. A colon is optional. A comment explaining what there is to do is required. The main purpose is to have a consistent TODO format that can 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

  • Use def with parentheses when there are parameters. Omit the parentheses when the method doesn't accept any parameters.[link]

    defsome_method# body omittedenddefsome_method_with_parameters(arg1,arg2)# body omittedend
  • Do not use default arguments. Use an options hash instead.[link]

    # baddefobliterate(things,gently=true,except=[],at=Time.now) ... end# gooddefobliterate(things,options={})default_options={:gently=>true,# obliterate with soft-delete:except=>[],# skip obliterating these things:at=>Time.now,# don't obliterate them until later}options.reverse_merge!(default_options) ... end
  • Avoid single-line methods. Although they are somewhat popular in the wild, there are a few peculiarities about their 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 uses parentheses.[link]

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

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

    # badnil?()# goodnil?
  • If the method doesn't return a value (or we don't care about the return), parentheses are optional. (Especially if the arguments 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 the last argument, do not use {} during invocation. [link]

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

Conditional Expressions

Conditional keywords

  • Never use then for multi-line if/unless. [link]

    # badifsome_conditionthen ... end# goodifsome_condition ... end
  • Never use do for multi-line while or until.[link]

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

  • Modifier if/unless usage is okay when the body is simple, the condition is simple, and the whole thing fits on one line. Otherwise, avoid modifier if/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 use unless with else. Rewrite these with the positive case first.[link]

    # badunlesssuccess?puts'failure'elseputs'success'end# goodifsuccess?puts'success'elseputs'failure'end
  • Avoid unless with multiple conditions.[link]

    # badunlessfoo? && bar? ... end# okayif !(foo? && bar?) ... end
  • Don't use parentheses around the condition of an if/unless/while. [link]

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

Ternary operator

  • Avoid the ternary operator (?:) except in cases where all expressions are extremely trivial. However, do use the ternary operator(?:) over if/then/else/end constructs for single line conditionals.[link]

    # badresult=ifsome_conditionthensomethingelsesomething_elseend# goodresult=some_condition ? something : something_else
  • Use one expression per branch in a ternary operator. This also means that ternary operators must not be nested. Prefer if/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 ternary operator), use if/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

Syntax

  • Never use for, unless you know exactly why. Most of the time iterators should be used instead. for is implemented in terms of each (so you're adding a level of indirection), but with a twist - for doesn't introduce a new scope (unlike each) and variables defined in its block will be visible outside it.[link]

    arr=[1,2,3]# badforeleminarrdoputselemend# goodarr.each{ |elem| putselem}
  • Prefer {...} over do...end for single-line blocks. Avoid using {...} for multi-line blocks (multiline chaining is always ugly). Always use do...end for "control flow" and "method definitions" (e.g. in Rakefiles and certain DSLs). Avoid do...end when 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 and whether the block's content can be extracted into nifty methods.

  • Use shorthand self assignment operators whenever 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 class definitions. When it is appropriate to use a semicolon, it should be directly adjacent to the statement it terminates: there should be no space 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 includes classes 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()
  • Avoid return 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 = in conditionals[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 boolean variables. (Consider what would happen if the current value happened to be false.)[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 but one-liner scripts is discouraged. Prefer long form versions such as $PROGRAM_NAME.[link]

  • When a method block takes only one argument, and the body consists solely of reading an attribute or calling one 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?)
  • Prefer some_method over self.some_method when calling 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 language and is good to use:

    1. When defining a class method: def self.some_method.
    2. The left hand side when calling an assignment method, including assigning an attribute when self is an ActiveRecord model: self.guest = user.
    3. Referencing the current instance's class: self.class.

Naming

  • Use snake_case for methods and variables. [link]

  • Use CamelCase for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.) [link]

  • Use SCREAMING_SNAKE_CASE for other constants.[link]

  • The names of predicate methods (methods that 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 modify self or the arguments, exit!, etc.) should end with an exclamation mark. Bang methods should only exist if a non-bang method exists. (More on this.) [link]

  • Name throwaway variables _. [link]

    payment,_=Payment.complete_paypal_payment!(params[:token],native_currency,created_at)

Classes

  • Avoid the usage of class (@@) variables due 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 one class variable. Class instance variables should usually be preferred over class variables.

  • Use def self.method to define singleton methods. This makes the methods more resistant to refactoring changes. [link]

    classTestClass# baddefTestClass.some_method ... end# gooddefself.some_other_method ... end
  • Avoid class << 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 the public, protected, and private methods as much the method definitions they apply to. Leave one blank 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 the Exception 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 specify RuntimeError explicitly in the two argument version of raise. Prefer error sub-classes for clarity and explicit 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 arguments to raise, 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

  • Prefer map over collect.[link]

  • Prefer detect over find. The use of find is ambiguous with regard to ActiveRecord's find method - detect makes clear that you're working with a Ruby collection, not an AR object. [link]

  • Prefer reduce over inject. [link]

  • Prefer size over either length or count for performance reasons.[link]

  • Prefer literal array and hash creation notation 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]={}}
  • Favor Array#join over Array#* 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 string symbols when possible.[link]

    # bad:"symbol"# good:symbol
  • Use Hash#key? instead of Hash#has_key? and Hash#value? instead of Hash#has_value?. According to 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 code more readable, and use trailing commas to ensure that parameter changes don'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 an Array that spans more than 1 line[link]

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

Strings

  • Prefer string interpolation instead of string 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 are composing 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 using String#+ when you need to construct large data chunks. Instead, use String#<<. Concatenation mutates the string instance in-place and is always faster than String#+, which creates a bunch of new string objects.[link]

    # good and also fasthtml=''html << '<h1>Page title</h1>'paragraphs.eachdo |paragraph| html << "<p>#{paragraph}</p>"end
  • 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 track what 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 they match start/end of line, not string endings. If you want to match the whole string use: \A and \z.[link]

    string="some injection\nusername"string[/^username$/]# matchesstring[/\Ausername\z/]# don't match
  • Use x modifier for complex regexps. This makes them more readable and you can add some useful comments. Just be careful as spaces 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 curly braces, brackets, or pipes when using %-literal delimiters for consistency, and because the behavior of %-literals is closer to method calls 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 require both interpolation and embedded double-quotes. For multi-line strings, prefer heredocs.[link]

    # bad - no interpolation needed%(<div class="text">Some text</div>)# should be '<div class="text">Some text</div>'# bad - no double-quotes%(This is #{quality} style)# should be "This is #{quality} style"# bad - multiple lines%(<div>\n<span class="big">#{exclamation}</span>\n</div>)# should be a heredoc.# good - requires interpolation, has quotes, single line%(<tr><td class="name">#{name}</td>)
  • Use %r only for regular expressions matching more than 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 a command with backquotes in it (which is rather unlikely). [link]

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

Rails

  • When immediately returning after calling render or redirect_to, put return 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 the relation in a lambda. A naked relation forces a database connection to be established 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 and determine its style. If they use spaces around all their arithmetic operators, you should too. If their comments have little boxes of hash marks around them, make your comments have little boxes of hash marks around them too.

The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you're saying rather than on how you're saying 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 looks drastically different from the existing code around it, it throws readers out of 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

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published