Sandi Metz best practise advices about application design

1) If you do design too early, you’ll waste your efforts.

2) If you never do design, your code will become a painful mess.

3) A time will come when investing in design will save you money.

4) Simple procedures require little design and are cheap to maintain.

5) Procedures become more complex over time, and more expensive to maintain.

6) Object-oriented code is more cost-effective than complex procedural code.

7) The procedures that are most important to your domain change more than those that are incidental to your domain.

8) The procedures that are important to your domain increase in complexity faster than other code.

9) It’s difficult to be aware of the exact moment when your application crosses the design payoff line.

10) You become aware that you have passed the design payoff line because velocity slows and suffering increases.

11) The most important code will be the most out-of-control by the time you realize you’ve passed the design payoff line.

12) Moderately complex procedures are easy to convert to OO.

13) Extremely complex procedures are more difficult to convert to OO.

14) Your attempts to convert moderately complicated procedures to OO generally succeed.

15) Your attempts to convert extremely complicated procedures to OO often fail.

 

Clean way of initializing service objects in ruby

# service object class
class FancyObject
  attr_reader :entity

  def self.perform(params)
    new(params).perform
  end

  def perform
    ApplicationRecord.transaction do
      # entity processing logic here

      entity.save
      entity
    end
  end

  private

  def initialize(params)
    @entity   = Entity.new(params)
  end
end

# controller:
@entity = FancyObject.perform(entity_params)

if @entity.valid?
  #...
end
 

Adding postgres index with condition.

For example, If you need only 1 admin on each project.

class AddUsers < ActiveRecord::Migration[5.1]
  def change
	create_table :users do |t|
      t.integer :project_id, null: false
      t.string :name, null: false
      t.integer :role, null: false

      t.timestamps
    end

    reversible do |direction|
	  direction.up do
        # Partial unique index
        execute <<-SQL
          CREATE UNIQUE INDEX unique_user_role_in_project ON users (project_id, role) WHERE role = 'admin';
        SQL
      end

      direction.down do
        # Remove unique index
        execute <<-SQL
          DROP INDEX IF EXISTS unique_user_role_in_project;
        SQL
      end
    end
  end
end
 

Slim template data attributes for a tag example

div*{'data-toggle'=> 'modal', 'data-target'=> "#approval_modal_#{keyword.id}"}
 

Using merge on join for records filtering

# Returns all the accounts that have unread messages.
  def self.with_unread_messages
    joins(:messages).merge( Message.unread )
  end
 

Bash shortcuts

CTRL-A Перемещение курсора в начало строки
CTRL-E Перемещение курсора в конец строки
CTRL-R Поиск по истории
CTRL-W Вырезать последнее слово
CTRL-U Вырезать всё до курсора
CTRL-K Вырезать всё после курсора
CTRL-Y Вернуть последнюю вырезанную строку
CTRL-_ Отмена
CTRL-L Очистка экрана терминала
 

Replace old rocket style ruby hash syntax with ruby-1.9 style bash script

find . -name \*.rb -exec perl -p -i -e 's/([^:]):(\w+)\s*=>/\1\2:/g' {} \;