実世界のタスクでのメタプログラミング

こんにちは!この記事では、実際の一般的な問題の例を使用してメタプログラミングについて説明したいと思います。





誰かがメタプログラミングについて話すとき、古い学校のコーダーは怒りを覚えます。





これには理由があり、大規模なプロジェクトでは、コードが非常に読みにくくなるため、メタプログラミングを使用するのはおかしなことに思えるかもしれません。そして、外部の専門家がプロジェクトに参加した場合、彼はさらにこのメタコードの何も理解しません。





しかし、それは彼らが言うほど単純ではありません-悪いツールはありません。この記事では、メタプログラミングがコードをよりクリーンにし、日常的な繰り返しを排除するのにどのように役立つかを実際の実例で示します。そして、メタマジックであなたを喜ばせるでしょう。





ウィキペディアからのヘルプ

メタプログラミングは、作業の結果として他のプログラムを生成するプログラム(特に、ソースコードのコンパイル段階)、または実行中に自分自身を変更するプログラム(自己変更コード)の作成に関連するプログラミングの一種です。 。1つ目は、プログラマーが完全に手作業でプログラムを作成する場合よりも少ない時間と労力でプログラムを取得できるようにし、2つ目は、コードのプロパティ(サイズとパフォーマンス)を向上させることができます。





これで紹介は終わりです。それでは、実際の部分に移り、問題の本質についてお話ししたいと思います。

さらに、特にRuby言語とRailsフレームワークについて説明します。Rubyには、メタプログラミングの反省と素晴らしい機会があります。ほとんどのgem、モジュール、およびフレームワークは、強力なリフレクションツールで構築されています。





フォトジョシュア・フラーUnsplash





Railsで何かを書いた人は、Rails Adminのような宝石に出くわした可能性が高いです。Railsのプロジェクトでそれを使用しようとしたことがない場合、またはアナログを使用している場合は、ほとんど箱から出してすぐに使用できるので、これを行うことを強くお勧めします。システム用の本格的なCMSを入手してください。





したがって、不快な機能、 has_oneアソシエーションの問題があります。





has_one . 1. , .





写真1
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

      
      







. has_one , . .









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

      
      







メタプログラミング技術を使用することの実用的な価値を示すことができたと思います。もちろん、それを使用するかどうかはあなたが決めます。頻繁に使用し、場違いに使用すると、プロジェクトは完全に読み取り不能になり、デバッグが困難になりますが、正しく使用すると、逆に、コードの量が減り、読みやすさが向上し、日常的な作業が不要になります。読んでくださった皆様、ありがとうございました!








All Articles