Sejak memasang "dark" theme, saya cenderung menjadi malas menulis. Untuk sementara, dark theme saya disable dulu yaa. Terima kasih (^_^) (bandithijo, 2024/09/15) ●

بسم الله الرحمن الرحيم

Pendahuluan

Pada catatan kali ini saya ingin memodifikasi output dari nama attribute yang terlalu panjang menjadi lebih pendek di Ruby on Rails.

Masalah

Saya memiliki method geofences yang mengembalikan colllection of hash data dari model geofeonce.

Model geofence memiliki attributes,

:id, :created_at, :updated_at, :name, :description, :coordinates, :incoming_notification, :outgoing_notification

Saya hanya ingin mengambil attributes: :id, :incoming_notification, :outgoing_notification.

FILEapp/geofences_controller.rb
1
2
3
4
5
def geofences
  {
    geofences: Geofence.all.order(id: :asc).as_json(only: [:id, :incoming_notification, :outgoing_notification])
  }
end

Outputnya,

{
    "geofences": [
        {
            "id": 1,
            "incoming_notification": true,
            "outgoing_notification": false
        },
        {
            "id": 2,
            "incoming_notification": false,
            "outgoing_notification": true
        },
        {
            "id": 3,
            "incoming_notification": true,
            "outgoing_notification": false
        },
        {
            "id": 4,
            "incoming_notification": false,
            "outgoing_notification": true
        }
    ]
}

Karena nama attribute :incoming_notification dan :outgoing_notification terlalu panjang, saya akan ganti menjadi :in dan :out. 1

Pemecahan Masalah

Algoritma Pertama

FILEapp/geofences_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
# First algorithm
def geofences
  {
    geofences: Geofence.all.order(id: :asc)
      .as_json(only: [:id, :incoming_notification, :outgoing_notification])
      .each { |attribute|
        attribute.tap { |key|
          key[:in] = key.delete('incoming_notification')
          key[:out] = key.delete('outgoing_notification')
        }
      }
  }
end

Algoritma Kedua

FILEapp/geofences_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Second algorithm
def geofences
  geofences = Geofence.all.order(id: :asc)

  transformed_geofences = geofences.map do |geofence|
    {
      id: geofence.id,
      in: geofence.incoming_notification,
      out: geofence.outgoing_notification
    }
  end

  { geofences: transformed_geofences }
end

Saya menulis 2 pendekatan. Namun, saya cenderung memilih algoritma kedua.

Alasannya adalah,

Database Query Optimization:

  1. algoritma pertama, diambil semua data, lalu dilakukan filtering dan tranformation dengan .as_json
  2. algoritman kedua, hanya mengambil attribute yang diperlukan :id, :incoming_notification, :outgoing_notification dengan .map(), hal ini berpotensi untuk meminimalisir query time ke database

Reduced Object Mutation:

  1. algoritman pertama, menggunakan .each dengan .tap untuk memodifikasi Hash Object, hal ini terkadang dapat menyebabkan behaviour yang tidak dapat diprediksi sehingga menimbulkan bug.
  2. algoritma kedua, langsung membuat Hash Object dengan attribute yang diperlukan tanpa meodifikasi data aslinya, tentu saja ini menjadi pendekatan yang cukup aman

Hasilnya,

{
    "geofences": [
        {
            "id": 1,
            "in": true,
            "out": false
        },
        {
            "id": 2,
            "in": false,
            "out": true
        },
        {
            "id": 3,
            "in": true,
            "out": false
        },
        {
            "id": 4,
            "in": false,
            "out": true
        }
    ]
}

Pesan Penulis

Terima kasih sudah mampir yaa.

Referensi


Penulis

bandithijo

My journey kicks off from reading textbooks as a former Medical Student to digging bugs as a Software Engineer – a delightful rollercoaster of career twists. Embracing failure with the grace of a Cat avoiding water, I've seamlessly transitioned from Stethoscope to Keyboard. Armed with ability for learning and adapting faster than a Heart Beat, I'm on a mission to turn Code into a Product.

- Rizqi Nur Assyaufi

944e8edeccab170ecee65673676b75514b2f62ed