Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby on Rails
Code

Kueri dalam Rails, Bagian 2

by
Length:LongLanguages:

Indonesian (Bahasa Indonesia) translation by Ilham Saputra (you can also view the original English article)

Di artikel kedua ini, kami akan sedikit lebih dalam ke pertanyaan Rekaman Aktif di Rails. Jika Anda masih baru dalam SQL, saya akan menambahkan contoh yang cukup sederhana sehingga Anda dapat ikut serta dan mengambil sintaks sedikit saat kita melanjutkan.

Yang sedang berkata, itu pasti akan membantu jika Anda menjalankan tutorial SQL cepat sebelum Anda kembali untuk terus membaca. Kalau tidak, luangkan waktu Anda untuk memahami pertanyaan SQL yang kami gunakan, dan saya berharap bahwa pada akhir seri ini ia tidak akan merasa mengintimidasi lagi.

Sebagian besar benar-benar mudah, tetapi sintaksnya agak aneh jika Anda baru saja mulai dengan pengkodean—terutama di Ruby. Bertahanlah, itu bukan ilmu roket!

Topik

  • Includes & Eager Loading
  • Joining Tables
  • Eager Loading
  • Scopes
  • Aggregations
  • Dynamic Finders
  • Specific Fields
  • Custom SQL

Includes & Eager Loading

Kueri ini mencakup lebih dari satu tabel basis data untuk dikerjakan dan mungkin yang paling penting untuk diambil dari artikel ini. Itu bermuara pada ini: alih-alih melakukan beberapa pertanyaan untuk informasi yang tersebar di beberapa tabel, includes mencoba untuk menjaga ini ke minimum. Konsep kunci di balik ini disebut "eager loading" dan berarti bahwa kita memuat objek terkait ketika kita menemukan.

Jika kami melakukannya dengan mengulangi kumpulan objek dan kemudian mencoba mengakses catatan terkait dari tabel lain, kami akan mengalami masalah yang disebut "masalah permintaan N + 1". Misalnya, untuk masing-masing agent.handler dalam koleksi agen, kami akan memecat pertanyaan yang terpisah untuk agen dan penangannya. Itulah yang perlu kita hindari karena ini tidak berskala sama sekali. Sebagai gantinya, kami melakukan hal berikut:

Rails

Jika sekarang kita beralih ke sekumpulan agen seperti itu—dengan diskon bahwa kita belum membatasi jumlah catatan yang dikembalikan untuk saat ini—kita akan berakhir dengan dua pertanyaan bukannya mungkin satu trilyun.

SQL

Agen yang satu ini dalam daftar memiliki dua penangan, dan ketika kami sekarang meminta objek agen untuk penangannya, tidak ada permintaan basis data tambahan yang perlu dipecat. Kita bisa mengambil langkah ini lebih jauh, tentu saja, dan ingin memuat beberapa catatan tabel terkait. Jika kami perlu memuat tidak hanya penangan tetapi juga misi terkait agen untuk alasan apa pun, kami dapat menggunakan includes seperti ini.

Rails

Sederhana! Hanya berhati-hatilah menggunakan versi tunggal dan jamak untuk menyertakan. Mereka bergantung pada asosiasi model Anda. Asosiasi has_many menggunakan bentuk jamak, sedangkan belongs_to atau has_one membutuhkan versi tunggal, tentu saja. Jika Anda perlu, Anda juga bisa memasukkan klausa where untuk menentukan kondisi tambahan, tetapi cara yang lebih disukai menentukan kondisi untuk tabel terkait yang ingin dimuat adalah dengan menggunakan gabungan joins.

Satu hal yang perlu diingat tentang eager loading adalah bahwa data yang akan ditambahkan akan dikirim kembali sepenuhnya ke Rekaman Aktif—yang pada gilirannya membangun objek Ruby termasuk atribut-atribut ini. Ini berbeda dengan "hanya" bergabung dengan data, di mana Anda akan mendapatkan hasil virtual yang dapat Anda gunakan untuk perhitungan, misalnya, dan akan lebih sedikit menguras memori daripada memasukkan.

Joining Tables

Joining tables adalah alat lain yang memungkinkan Anda menghindari mengirimkan terlalu banyak permintaan yang tidak perlu ke dalam pipa. Skenario umum adalah menggabungkan dua tabel dengan satu kueri yang mengembalikan semacam catatan gabungan. joins hanyalah metode finder Rekaman Aktif yang memungkinkan Anda—dalam istilah SQL—JOIN tabel. Kueri ini dapat mengembalikan catatan yang digabungkan dari beberapa tabel, dan Anda mendapatkan tabel virtual yang menggabungkan catatan dari tabel ini. Ini cukup tepat ketika Anda membandingkannya dengan mengirim semua jenis kueri untuk setiap tabel. Ada beberapa jenis data yang tumpang tindih yang bisa Anda dapatkan dengan pendekatan ini.

Gabung dalam adalah modus operandi default untuk joins. Ini cocok dengan semua hasil yang cocok dengan id tertentu dan perwakilannya sebagai kunci asing dari objek atau tabel lain. Dalam contoh di bawah ini, sederhananya: beri saya semua misi tempat id misi muncul sebagai mission_id di tabel agen. "agents"."mission_id" = "missions"."id". Batin bergabung dengan mengecualikan hubungan yang tidak ada.

Rails

SQL

Jadi kami mencocokkan misi dan agen yang menyertainya—dalam satu permintaan! Tentu, kami bisa mendapatkan misi pertama, beralih satu per satu, dan meminta agen mereka. Tapi kemudian kita akan kembali ke "N + 1 masalah permintaan" yang mengerikan. Tidak terima kasih!

Yang juga bagus tentang pendekatan ini adalah bahwa kami tidak akan mendapatkan kasus nol dengan gabungan batin; kami hanya mendapatkan catatan yang dikembalikan yang cocok dengan id mereka ke kunci asing di tabel terkait. Jika kita perlu menemukan misi, misalnya, yang tidak memiliki agen, kita akan membutuhkan penggabung luar. Karena saat ini melibatkan penulisan OUTER JOIN SQL Anda sendiri, kami akan membahasnya di artikel terakhir. Kembali ke penggabungan standar, Anda juga dapat bergabung dengan beberapa tabel terkait.

Rails

Dan Anda dapat menambahkan beberapa klausa where ini untuk menentukan pencari Anda lebih banyak lagi. Di bawah ini, kami hanya mencari misi yang dieksekusi oleh James Bond dan hanya agen yang termasuk misi 'Moonraker' dalam contoh kedua.

SQL

Rails

SQL

Dengan joins, Anda juga harus memperhatikan penggunaan tunggal dan jamak asosiasi model Anda. Karena kelas Mission saya has_many :agents, kita dapat menggunakan jamak. Di sisi lain, untuk kelas Agent adalah belongs_to :mission, hanya versi tunggal yang bekerja tanpa meledak. Detail kecil yang penting: bagian where yang lebih sederhana. Karena Anda memindai beberapa baris dalam tabel yang memenuhi kondisi tertentu, bentuk jamak selalu masuk akal.

Scopes

Lingkup adalah cara praktis untuk mengekstraksi kebutuhan kueri umum ke dalam metode bernama Anda sendiri. Dengan begitu mereka sedikit lebih mudah untuk diedarkan dan juga mungkin lebih mudah untuk dipahami jika orang lain harus bekerja dengan kode Anda atau jika Anda perlu mengunjungi kembali pertanyaan tertentu di masa depan. Anda dapat mendefinisikannya untuk model tunggal tetapi menggunakannya juga untuk asosiasi mereka.

Langit adalah batas sesungguhnya — joins, includes, dan where semua permainan adil! Karena cakupan juga mengembalikan objek ActiveRecord::Relations, Anda dapat rantai mereka dan memanggil lingkup lain di atasnya tanpa ragu-ragu. Mengekstraksi cakupan seperti itu dan merantai mereka untuk pertanyaan yang lebih kompleks sangat berguna dan membuat yang lebih lama semakin mudah dibaca. Lingkup didefinisikan melalui sintaks "stabby lambda":

Rails

SQL

Seperti yang dapat Anda lihat dari contoh di atas, menemukan James Bond jauh lebih baik ketika Anda hanya bisa meringkas cakupan. Dengan begitu Anda dapat mencampur dan mencocokkan berbagai pertanyaan dan tetap DRY pada saat yang sama. Jika Anda membutuhkan ruang lingkup melalui asosiasi, mereka juga siap membantu Anda:

Anda juga dapat mendefinisikan kembali default_scope ketika Anda melihat sesuatu seperti Mission.all.

SQL

Aggregations

Bagian ini tidak terlalu maju dalam hal pemahaman yang terlibat, tetapi Anda akan membutuhkannya lebih sering daripada tidak dalam skenario yang dapat dianggap sedikit lebih maju daripada rata-rata pencari Anda—seperti .all, .first, .find_by_id atau apa pun. Pemfilteran berdasarkan perhitungan dasar, misalnya, kemungkinan besar adalah sesuatu yang pemula tidak dapat langsung hubungi. Apa yang sebenarnya kita lihat di sini?

  • sum
  • count
  • minimum
  • maximum
  • average

Mudah, kan? Yang keren adalah bahwa alih-alih mengulangi kumpulan objek yang dikembalikan untuk melakukan perhitungan ini, kita dapat membiarkan Rekaman Aktif melakukan semua pekerjaan ini untuk kita dan mengembalikan hasil ini dengan kueri—dalam satu permintaan lebih disukai. Bagus ya

  • count

Rails

SQL

  • average

Rails

SQL

Karena kita sekarang tahu bagaimana kita dapat menggunakan joins, kita dapat mengambil satu langkah lebih jauh dan hanya meminta rata-rata gadget yang dimiliki agen pada misi tertentu, misalnya.

Rails

SQL

Mengelompokkan jumlah rata-rata gadget berdasarkan nama misi menjadi sepele pada saat itu. Lihat lebih lanjut tentang pengelompokan di bawah ini:

Rails

SQL

  • sum

Rails

SQL

  • maximum

Rails

SQL

  • minimum

Rails

SQL

Perhatian!

Semua metode agregasi ini tidak membiarkan Anda melakukan hal-hal lain—itu adalah terminal. Urutan penting untuk melakukan perhitungan. Kami tidak mendapatkan objek ActiveRecord::Relation kembali dari operasi ini, yang membuat musik berhenti pada saat itu—kami malah mendapatkan hash atau angka. Contoh di bawah ini tidak akan berfungsi:

Rails

Grouped

Jika Anda ingin perhitungan dipecah dan diurutkan ke dalam grup logis, Anda harus menggunakan klausa GROUP dan tidak melakukan ini di Ruby. Yang saya maksud dengan itu adalah Anda harus menghindari iterasi di atas grup yang berpotensi menghasilkan banyak pertanyaan.

Rails

SQL

Contoh ini menemukan semua agen yang dikelompokkan ke misi tertentu dan mengembalikan hash dengan jumlah rata-rata gadget yang dihitung sebagai nilainya—dalam satu permintaan! Ya! Hal yang sama berlaku untuk perhitungan lain juga, tentu saja. Dalam hal ini, sangat masuk akal untuk membiarkan SQL melakukan pekerjaannya. Jumlah kueri yang kami gunakan untuk agregasi ini terlalu penting.

Dynamic Finders

Untuk setiap atribut pada model Anda, ucapkan name, email_address, favorite_gadget dan sebagainya, Rekaman Aktif memungkinkan Anda menggunakan metode pencari yang sangat mudah dibaca yang secara dinamis dibuat untuk Anda. Kedengarannya samar, saya tahu, tapi itu tidak berarti apa pun selain find_by_id atau find_by_favorite_gadget. Bagian find_by adalah standar, dan Rekaman Aktif hanya menyelipkan nama atribut untuk Anda. Anda bahkan dapat menambahkan ! jika Anda ingin pencari itu meningkatkan kesalahan jika tidak ada yang dapat ditemukan. Bagian yang sakit adalah, Anda bahkan dapat menghubungkan metode pencari dinamis ini bersama-sama. Seperti ini:

Rails

SQL

Tentu saja Anda bisa menjadi gila dengan ini, tapi saya pikir itu kehilangan pesona dan kegunaannya jika Anda melampaui dua atribut:

Rails

SQL

Dalam contoh ini, tetap baik untuk melihat cara kerjanya di bawah tenda. Setiap _and_ baru menambahkan operator SQL AND untuk secara logis mengikat atribut. Secara keseluruhan, manfaat utama finder dinamis adalah keterbacaan—memasukkan terlalu banyak atribut dinamis akan kehilangan keuntungan dengan cepat. Saya jarang menggunakan ini, mungkin sebagian besar ketika saya bermain-main di konsol, tetapi pasti baik untuk mengetahui bahwa Rails menawarkan tipuan kecil yang rapi ini.

Specific Fields

Rekaman Aktif memberi Anda opsi untuk mengembalikan objek yang sedikit lebih fokus tentang atribut yang dibawanya. Biasanya, jika tidak ditentukan sebaliknya, permintaan akan meminta semua bidang dalam satu baris melalui * (SELECT "agents".*), Dan kemudian Rekaman Aktif membangun objek Ruby dengan set atribut lengkap. Namun, Anda dapat select hanya bidang tertentu yang harus dikembalikan oleh kueri dan membatasi jumlah atribut yang perlu 'dibawa-bawa' oleh objek Ruby Anda.

Rails

SQL

Rails

SQL

Seperti yang Anda lihat, objek yang dikembalikan hanya akan memiliki atribut yang dipilih, ditambah id mereka tentu saja—yaitu diberikan dengan objek apa pun. Tidak ada bedanya jika Anda menggunakan string, seperti di atas, atau simbol—kueri akan sama.

Rails

Peringatan: Jika Anda mencoba mengakses atribut pada objek yang belum Anda pilih dalam kueri, Anda akan menerima MissingAttributeError. Karena id akan secara otomatis disediakan untuk Anda, Anda dapat meminta id tanpa memilihnya.

Custom SQL

Terakhir, Anda dapat menulis SQL khusus sendiri melalui find_by_sql. Jika Anda cukup percaya diri dalam SQL-Fu Anda sendiri dan perlu beberapa panggilan khusus ke database, metode ini mungkin sangat berguna di kali. Tapi ini cerita lain. Jangan lupa untuk memeriksa metode pembungkus Rekaman Aktif terlebih dahulu dan hindari menciptakan kembali roda tempat Rails mencoba menemui Anda lebih dari setengah jalan.

Rails

Tidak mengejutkan, ini menghasilkan:

SQL

Karena cakupan dan metode kelas Anda sendiri dapat digunakan secara bergantian untuk kebutuhan pencari kustom Anda, kami dapat mengambil langkah ini lebih jauh untuk kueri SQL yang lebih kompleks.

Rails

Kita bisa menulis metode kelas yang merangkum SQL di dalam dokumen Here. Ini memungkinkan kita menulis string multi-line dengan cara yang sangat mudah dibaca dan kemudian menyimpan string SQL di dalam variabel yang dapat kita gunakan kembali dan masukkan ke find_by_sql. Dengan begitu kami tidak memplester banyak kode kueri di dalam pemanggilan metode. Jika Anda memiliki lebih dari satu tempat untuk menggunakan kueri ini, itu DRY juga.

Karena ini seharusnya ramah pemula dan bukan tutorial SQL saja, saya membuat contoh sangat minimalis karena suatu alasan. Namun, teknik untuk pertanyaan yang jauh lebih kompleks sama saja. Sangat mudah untuk membayangkan memiliki kueri SQL khusus di sana yang membentang lebih dari sepuluh baris kode.

Lakukan sebanyak yang Anda inginkan—secara masuk akal! Itu bisa menjadi penyelamat. Sepatah kata tentang sintaksis di sini. Bagian SQL hanyalah pengidentifikasi di sini untuk menandai awal dan akhir string. Saya yakin Anda tidak akan terlalu membutuhkan metode ini—mari berharap! Ini benar-benar memiliki tempatnya, dan Rails tidak akan sama tanpanya—dalam kasus yang jarang terjadi, Anda benar-benar ingin menyempurnakan SQL Anda sendiri dengannya.

Pikiran terakhir

Saya harap Anda mendapat sedikit lebih nyaman menulis kueri dan membaca SQL mentah ol yang ditakuti. Sebagian besar topik yang kami bahas dalam artikel ini sangat penting untuk menulis kueri yang berhubungan dengan logika bisnis yang lebih kompleks. Luangkan waktu Anda untuk memahami ini dan bermain-main sedikit dengan pertanyaan di konsol.

Saya cukup yakin bahwa ketika Anda meninggalkan tanah tutorial, cepat atau lambat kredit Rails Anda akan naik secara signifikan jika Anda mengerjakan proyek kehidupan nyata pertama Anda dan perlu membuat kueri khusus sendiri. Jika Anda masih sedikit malu dengan topik itu, saya katakan cukup bersenang-senang dengannya—itu benar-benar bukan ilmu roket!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.