Halo! Pada artikel ini saya ingin berbicara tentang metaprogramming menggunakan contoh masalah umum yang nyata.
Ketika seseorang berbicara tentang metaprogramming, pembuat kode jadul akan marah.
Dan ada alasan untuk ini, dan pada proyek besar mungkin terlihat gila untuk menggunakan metaprogramming, karena kodenya menjadi sangat sulit untuk dibaca. Dan jika seorang spesialis dari luar bergabung dengan proyek tersebut, maka dia bahkan tidak akan mengerti apa pun dalam meta-code ini.
Tapi tidak sesederhana yang mereka katakan - tidak ada alat yang buruk. Pada artikel ini saya akan mencoba menunjukkan dengan contoh kerja nyata bagaimana metaprogramming dapat membantu membuat kode Anda lebih bersih dan menghilangkan pengulangan rutin. Dan akan membuatmu bersukacita dalam meta-magic.
Bantuan dari wikipedia
Metaprogramming adalah jenis pemrograman yang terkait dengan pembuatan program yang menghasilkan program lain sebagai hasil dari pekerjaannya (khususnya, pada tahap kompilasi kode sumbernya), atau program yang berubah sendiri selama eksekusi (kode modifikasi sendiri) . Yang pertama memungkinkan Anda mendapatkan program dengan waktu dan upaya yang lebih sedikit pada pengkodean daripada jika programmer menulis seluruhnya dengan tangan, yang kedua memungkinkan Anda untuk meningkatkan properti kode (ukuran dan kinerja).
Ini menyimpulkan pendahuluan. Sekarang saya ingin beralih ke bagian praktis dan memberi tahu Anda tentang esensi masalahnya
Selanjutnya kita akan berbicara tentang bahasa ruby ββdan khususnya kerangka Rails. Ruby memiliki refleksi dan peluang besar untuk metaprogramming. Kebanyakan permata, modul, dan kerangka kerja dibangun dengan alat refleksi yang kuat.
Foto oleh Joshua Fuller di Unsplash
Siapa pun yang menulis sesuatu di Rails kemungkinan besar menemukan permata seperti Admin Rails, jika Anda belum mencoba menggunakannya dalam proyek Anda di rel, atau jika Anda memiliki analog, saya sangat menyarankan melakukan ini, karena hampir di luar kotak Anda akan melakukannya. dapatkan CMS lengkap untuk sistem Anda.
Jadi ada fitur yang tidak menyenangkan , masalah dengan asosiasi has_one.
has_one . 1. , .
. has_one (draft) CMS.
class TechProcess < ApplicationRecord
include MdcSchema
has_many :executor_programs, inverse_of: :tech_process, foreign_key: :barcode_tech_process, primary_key: :barcode
validates :barcode, presence: true
validates :barcode, uniqueness: true
has_one :draft2tech_process, dependent: :destroy
has_one :draft, through: :draft2tech_process
has_many :tech_process2tech_operations
has_many :tech_operations, through: :tech_process2tech_operations
end
def draft_id
self.draft.try :id
end
def draft_id=(id)
self.draft = Draft.find_by_id(id)
end
, , , CMS.
, 15 has_one ? , DRY. . .
Meta
self.reflect_on_all_associations(:has_one).each do |has_one_association|
define_method("#{has_one_association.name}_id") do
self.send(has_one_association.name).try :id
end
define_method("#{has_one_association.name}_id=") do |id|
self.send("#{has_one_association.name}=",has_one_association.klass.find_by_id(id))
end
end
, has_one Rails Admin
. .
, . reflect_on_all_associations , "macro" :hasone has_one , , .
, has_one . , , define_method .
has_one rails admin.
"" , . - concern
require 'active_support/concern'
module HasOneHandler
extend ActiveSupport::Concern
included do
self.reflect_on_all_associations(:has_one).each do |has_one_association|
define_method("#{has_one_association.name}_id") do
self.send(has_one_association.name).try :id
end
define_method("#{has_one_association.name}_id=") do |id|
self.send("#{has_one_association.name}=",has_one_association.klass.find_by_id(id))
end
end
end
end
, . CMS has_one . , .
class TechProcess < ApplicationRecord
include MdcSchema
include HasOneHandler
has_many :executor_programs, inverse_of: :tech_process, foreign_key: :barcode_tech_process, primary_key: :barcode
validates :barcode, presence: true
validates :barcode, uniqueness: true
has_one :draft2tech_process, dependent: :destroy
has_one :draft, through: :draft2tech_process
has_many :tech_process2tech_operations
has_many :tech_operations, through: :tech_process2tech_operations
end
Saya berharap saya bisa menunjukkan nilai praktis dari penggunaan teknik metaprogramming. Tentu saja, Anda memutuskan apakah akan menggunakannya atau tidak. Jika Anda menggunakannya terlalu sering dan tidak pada tempatnya, maka proyek akan menjadi benar-benar tidak dapat dibaca dan sulit untuk di-debug, tetapi jika digunakan dengan benar, sebaliknya, mengurangi jumlah kode, meningkatkan keterbacaan dan menghilangkan pekerjaan rutin. Terima kasih untuk semua yang membacanya!