こんにちは!この記事では、実際の一般的な問題の例を使用してメタプログラミングについて説明したいと思います。
誰かがメタプログラミングについて話すとき、古い学校のコーダーは怒りを覚えます。
これには理由があり、大規模なプロジェクトでは、コードが非常に読みにくくなるため、メタプログラミングを使用するのはおかしなことに思えるかもしれません。そして、外部の専門家がプロジェクトに参加した場合、彼はさらにこのメタコードの何も理解しません。
しかし、それは彼らが言うほど単純ではありません-悪いツールはありません。この記事では、メタプログラミングがコードをよりクリーンにし、日常的な繰り返しを排除するのにどのように役立つかを実際の実例で示します。そして、メタマジックであなたを喜ばせるでしょう。
ウィキペディアからのヘルプ
メタプログラミングは、作業の結果として他のプログラムを生成するプログラム(特に、ソースコードのコンパイル段階)、または実行中に自分自身を変更するプログラム(自己変更コード)の作成に関連するプログラミングの一種です。 。1つ目は、プログラマーが完全に手作業でプログラムを作成する場合よりも少ない時間と労力でプログラムを取得できるようにし、2つ目は、コードのプロパティ(サイズとパフォーマンス)を向上させることができます。
これで紹介は終わりです。それでは、実際の部分に移り、問題の本質についてお話ししたいと思います。
さらに、特にRuby言語とRailsフレームワークについて説明します。Rubyには、メタプログラミングの反省と素晴らしい機会があります。ほとんどのgem、モジュール、およびフレームワークは、強力なリフレクションツールで構築されています。
Railsで何かを書いた人は、Rails Adminのような宝石に出くわした可能性が高いです。Railsのプロジェクトでそれを使用しようとしたことがない場合、またはアナログを使用している場合は、ほとんど箱から出してすぐに使用できるので、これを行うことを強くお勧めします。システム用の本格的なCMSを入手してください。
したがって、不快な機能、 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
メタプログラミング技術を使用することの実用的な価値を示すことができたと思います。もちろん、それを使用するかどうかはあなたが決めます。頻繁に使用し、場違いに使用すると、プロジェクトは完全に読み取り不能になり、デバッグが困難になりますが、正しく使用すると、逆に、コードの量が減り、読みやすさが向上し、日常的な作業が不要になります。読んでくださった皆様、ありがとうございました!