When I started Ruby, I used to comment - but kept them brief - because I thought that was what we were meant to do 
Then I came across a Ruby Gem by Nando Vieira and was really impressed by how well documented it was:
module PayPal
module Recurring
class Base
attr_accessor :amount
attr_accessor :cancel_url
attr_accessor :currency
attr_accessor :description
attr_accessor :note
attr_accessor :email
attr_accessor :failed
attr_accessor :frequency
attr_accessor :initial_amount
attr_accessor :initial_amount_action
attr_accessor :ipn_url
attr_accessor :locale
attr_accessor :outstanding
attr_accessor :payer_id
attr_accessor :period
attr_accessor :profile_id
attr_accessor :reference
attr_accessor :refund_type
attr_accessor :return_url
attr_accessor :start_at
attr_accessor :token
attr_accessor :transaction_id
attr_accessor :item_category
attr_accessor :item_name
attr_accessor :item_amount
attr_accessor :item_quantity
attr_accessor :trial_frequency
attr_accessor :trial_length
attr_accessor :trial_period
attr_accessor :trial_amount
def initialize(options = {})
options.each {|name, value| send("#{name}=", value)}
end
# Just a shortcut convenience.
#
def request # :nodoc:
@request ||= Request.new
end
# Request a checkout token.
#
# ppr = PayPal::Recurring.new({
# :return_url => "http://example.com/checkout/thank_you",
# :cancel_url => "http://example.com/checkout/canceled",
# :ipn_url => "http://example.com/paypal/ipn",
# :description => "Awesome - Monthly Subscription",
# :amount => "9.00",
# :currency => "USD"
# })
#
# response = ppr.request_token
# response.checkout_url
#
def checkout
params = collect(
:locale,
:amount,
:return_url,
:cancel_url,
:currency,
:description,
:ipn_url,
:item_category,
:item_name,
:item_amount,
:item_quantity
).merge(
:payment_action => "Authorization",
:no_shipping => 1,
:L_BILLINGTYPE0 => "RecurringPayments"
)
request.run(:checkout, params)
end
# Suspend a recurring profile.
# Suspended profiles can be reactivated.
#
# ppr = PayPal::Recurring.new(:profile_id => "I-HYRKXBMNLFSK")
# response = ppr.suspend
#
def suspend
request.run(:manage_profile, :action => :suspend, :profile_id => profile_id)
end
# Reactivate a suspended recurring profile.
#
# ppr = PayPal::Recurring.new(:profile_id => "I-HYRKXBMNLFSK")
# response = ppr.reactivate
#
def reactivate
request.run(:manage_profile, :action => :reactivate, :profile_id => profile_id)
end
# Cancel a recurring profile.
# Cancelled profiles cannot be reactivated.
#
# ppr = PayPal::Recurring.new(:profile_id => "I-HYRKXBMNLFSK")
# response = ppr.cancel
#
def cancel
request.run(:manage_profile, :action => :cancel, :profile_id => profile_id)
end
# Return checkout details.
#
# ppr = PayPal::Recurring.new(:token => "EC-6LX60229XS426623E")
# response = ppr.checkout_details
#
def checkout_details
request.run(:details, :token => token)
end
# Request payment.
#
# # ppr = PayPal::Recurring.new({
# :token => "EC-6LX60229XS426623E",
# :payer_id => "WTTS5KC2T46YU",
# :amount => "9.00",
# :description => "Awesome - Monthly Subscription"
# })
# response = ppr.request_payment
# response.completed? && response.approved?
#
def request_payment
params = collect(
:amount,
:return_url,
:cancel_url,
:ipn_url,
:currency,
:description,
:payer_id,
:token,
:reference,
:item_category,
:item_name,
:item_amount,
:item_quantity
).merge(:payment_action => "Sale")
request.run(:payment, params)
end
# Create a recurring billing profile.
#
# ppr = PayPal::Recurring.new({
# :amount => "9.00",
# :initial_amount => "9.00",
# :initial_amount_action => :cancel,
# :currency => "USD",
# :description => "Awesome - Monthly Subscription",
# :ipn_url => "http://example.com/paypal/ipn",
# :frequency => 1,
# :token => "EC-05C46042TU8306821",
# :period => :monthly,
# :reference => "1234",
# :payer_id => "WTTS5KC2T46YU",
# :start_at => Time.now,
# :failed => 1,
# :outstanding => :next_billing,
# :trial_period => :monthly,
# :trial_length => 1,
# :trial_frequency => 1,
# :trial_amount => 0.00
# })
#
# response = ppr.create_recurring_profile
#
def create_recurring_profile
params = collect(
:amount,
:initial_amount,
:initial_amount_action,
:currency,
:description,
:payer_id,
:token,
:reference,
:start_at,
:failed,
:outstanding,
:ipn_url,
:frequency,
:period,
:email,
:trial_length,
:trial_period,
:trial_frequency,
:trial_amount,
:item_category,
:item_name,
:item_amount,
:item_quantity
)
request.run(:create_profile, params)
end
# Update a recurring billing profile.
#
# ppr = PayPal::Recurring.new({
# :amount => "99.00",
# :currency => "USD",
# :description => "Awesome - Monthly Subscription",
# :note => "Changed plan to Gold",
# :ipn_url => "http://example.com/paypal/ipn",
# :reference => "1234",
# :profile_id => "I-VCEL6TRG35CU",
# :start_at => Time.now,
# :outstanding => :next_billing
# })
#
# response = ppr.update_recurring_profile
#
def update_recurring_profile
params = collect(
:amount,
:currency,
:description,
:note,
:profile_id,
:reference,
:start_at,
:outstanding,
:ipn_url,
:email
)
request.run(:update_profile, params)
end
# Retrieve information about existing recurring profile.
#
# ppr = PayPal::Recurring.new(:profile_id => "I-VCEL6TRG35CU")
# response = ppr.profile
#
def profile
request.run(:profile, :profile_id => profile_id)
end
# Request a refund.
# ppr = PayPal::Recurring.new({
# :profile_id => "I-VCEL6TRG35CU",
# :transaction_id => "ABCEDFGH",
# :reference => "1234",
# :refund_type => :partial,
# :amount => "9.00",
# :currency => "USD"
# })
# response = ppr.refund
#
def refund
params = collect(
:transaction_id,
:reference,
:refund_type,
:amount,
:currency,
:note
)
request.run(:refund, params)
end
private
# Collect specified attributes and build a hash out of it.
#
def collect(*args) # :nodoc:
args.inject({}) do |buffer, attr_name|
value = send(attr_name)
buffer[attr_name] = value if value
buffer
end
end
end
end
end
And started to do the same. Then some time afterwards DHH tweeted/blogged how he rarely comments, but instead gives his methods (i.e functions) long descriptive names - even if they get quite long.
If you work hard at being clear in your naming, you’ll also rarely need to write comments for the code. Comments are generally only needed when you failed to be clear enough in naming. Treat them as a code smell.
Here’s some of his examples:
def make_person_an_outside_subscriber_if_all_accesses_revoked
person.update_attribute(:outside_subscriber, true) if person.reload.accesses.blank?
end
def shift_records_upward_starting_at(position)
positioned_records.update_all "position = position - 1",
["position >= ?", position]
end
def someone_else_just_finished_writing?(document)
if event = document.current_version_event
!event.by_current_creator? and event.updated_at > 1.minute.ago
end
end
So I thought I’d try that. I regretted it
I think having good function names is great, but good comments are incredibly useful too.