Here are few Rails and general developer tips & tricks to

  • improve code readability
  • do things Rails way
  • improve productivity

They say "Good code is like a good joke: It needs no explanation".


1) idiomatic code

Instead of this code...

def delete(notes)
  notes = notes.where('notes.from = (?)', 'evernote')
  notes.any? && notes.map(&:destroy)
end

Better way is...

def delete(notes)
  notes.where('notes.from = (?)', 'evernote').map(&:destroy)
end

2) Rails way

Instead of this code...

identifier = resource.social_identifier
data = { identifier: identifier }
render json: data.to_json

Better way...

render json: { identifier: resource.social_identifier }.to_json

3) Avoiding unless to read naturally

Instead of this code...

(flash[:error] = resource.errors.full_messages.first) unless resource.save

Better way is...

resource.save or (flash[:error] = resource.errors.full_messages.first)

4) Conditional associations

Conditional associations come in handy when we want to access a subset of the children. For example, lets say we have User and Posts model. Now

class User
  has_many :posts
  has_many :authorized_posts, ->{ where(approved: true) }, class_name: 'Post'
end

User.find(1).authorized_posts # This will return posts that are approved by the admin.

5) The presence method:

The @object.presence method goes one step ahead than @object.present? by returning the attribute or value being checked for rather than just true. For example, lets say we have this nested hash

team = {name: 'Mumbai Indians', mascot: 'IPL', coach: {name: 'Anil Kumble', years: '1'}}

If we want to get the name of a coach for a given team, we could write the following in order to avoid an error when checking for a nested hash key that may or may not be there:

team[:coach][:name].present? ? team[:coach][:name] : nil

But it would be more terse to write as follows:

team[:coach][:name].presence

Both .present? and .presence return nil for falsey evaluations. Here’s the documentation for .presence method.


6) Following Ruby Style guide:

Ruby style guide says Avoid modifier if/unless usage at the end of a non-trivial multi-line block

# bad
10.times do
  # multi-line body omitted
end if some_condition

# good
if some_condition
  10.times do
    # multi-line body omitted
  end
end


# bad
@selected_uids.each do |serialized|
  @uids << serialized["value"]
end if @selected_uids

# good
if @selected_uids
  @selected_uids.each do |serialized|
     @uids << serialized["value"]
  end
end

7) Sandbox mode

When we load console for our rails app, any actions that we perform are executed against the development environment by default. Values or data in the database changes as a result of the model calls from console - so it persists. If we want to try things out without accidentally or inadvertently changing the data, we can start rails console in sandbox mode as follows

$ rails c --sandbox 

This gives me output as

Loading development environment in sandbox (Rails 3.2.19)
Any modifications you make will be rolled back on exit
2.1.2 :001 >

All the .create, .update, .save and any other database-related actions that we do in sandbox mode will not be persisted. The operations that we perform in this mode will only be effective for that session only. Once we quit the console, all our changes will be lost.


8) Pretend with rails generate command

The rails generate or rails g command is used many times during the lifetime of a project (i.e migration, rspec:install, or even to scaffold)

Sometimes the rails generate command may create or modify multiple files that we may not want to. If we want to find out what files will be created or modified, we can run a pretend migration using -p option as follows

$ blog_app  rails g model comment body:text post_id:integer -p

This command will not generate anything but will pretend and will show following output so that we know what all will be generated and modified.

invoke  active_record
      create    db/migrate/20141002023923_create_comments.rb
      create    app/models/comment.rb
      invoke    test_unit
      create      test/models/comment_test.rb
      create      test/fixtures/comments.yml

9) Amend a git commit using --amend option

Sometimes, after I git commit, I realise that I forgot to remove a debugger statement or have to make some other change. So rather than making a new commit, I can open previous commit using git commit --amend command which will not only include the changes from previous commit, but also allow me to edit the commit message. Thus --amend option with git commit opens up a previous git commit and attaches changes (that you have) to that git commit rather than making an entirely new commit.

git commit --amend

10) Code comments for better code readability

Leaving a blank comment line before a class, module or method definition makes the comment extra readable, e.g.:

# This method returns the answer
#
def answer
  43
end