【问题标题】:Metaprogramming necessary to DRY modules?DRY 模块需要元编程吗?
【发布时间】:2011-10-31 21:57:16
【问题描述】:

我在应用程序中命名空间代码作为练习。我所说的“锻炼”,完全是为了好玩。假设示例角色 PerformerManager 代表 20 个必须与辅助方法一起定义的角色中的 2 个。

class Role
  module Performer
    extend ActiveSupport::Concern

    module InstanceMethods
      def performer?(id = @current_user_id)
        true unless self.roles.where(user_id: id, name: 'Performer').empty?
      end

      def make_performer(id = @current_user_id)
        self.roles.new(user_id: id, name: 'Performer')
      end
    end

  end

  module Manager
    extend ActiveSupport::Concern

    module InstanceMethods
      def manager?(id = @current_user_id)
        true unless self.roles.where(user_id: id, name: 'Manager').empty?
      end

      def make_manager(id = @current_user_id)
        self.roles.new(user_id: id, name: 'Manager')
      end
    end

  end
end

选择角色会根据需要混合到其他模块中。每个模块都混合了一组不同的角色,

class Group
  module Roles
    extend ActiveSupport::Concern

    included do
      include Role::Manager
      include Role::Performer
      before_create :make_creator_manager

      protected
        def make_creator_manager
          make_manager @current_user_id if @current_user_id
        end
    end

  end
end

然后通过多态关联与单个模型相关联。

class Group < ActiveRecord::Base
  include Group::Roles
  attr_accessor :current_user_id
  has_many :roles, as: :restrictable
end

我可以用闭包来干掉方法的内容,但是由于方法的名称也遵循一个模式,metaprogramming 会更有意义吗? ruby example

元编程在 ruby​​ 中是否足够普遍,以至于无论谁(理论上)接管这个项目都能够毫无困难地维护它?


编辑 1:角色迁移可能与本次讨论相关

class CreateRoles < ActiveRecord::Migration
  def change
    create_table :roles do |t|
      t.belongs_to :user
      t.references :restrictable, polymorphic: true
      t.string :name

      t.timestamps
    end
    add_index :roles, :user_id
    add_index :roles, [:restrictable_id, :restrictable_type]
  end
end

【问题讨论】:

    标签: ruby-on-rails ruby metaprogramming maintenance


    【解决方案1】:

    这很常见,但它是否可维护更多地取决于您提供的文档和开发人员的心态。

    理想情况下,元编程消失在应用程序中,很少需要触及。为此,它会慢慢做同样的事情——制作特定于角色的模式。元编程本身需要维护的可能性有多大?

    只要有一条从“嘿,该功能从何而来?”的路径。对于注入功能的代码,我认为这很好,特别是因为此功能的“元”范围非常有限。

    我看到的唯一潜在问题是需要清楚地定义合法角色名称的外观,并确保如果它不是简单的 alpha 字符,它将映射到什么方法名称是显而易见的。

    【讨论】:

    • define what a legal role name looks like tinker
    • @Alex 或者如果是,如果它应该;)
    【解决方案2】:

    看起来很复杂,你确定没有更简单的方法吗?

    一方面,STI(单表继承)或只是常规的 oo 继承(如果您不使用活动记录)似乎更合适:

    user.type?(Manager) 而不是manager?(user_id)

    user.update_attributes(:type =&gt; 'Manager') 而不是make_manager(user_id)

    如果您打算进行元编程,我会在此时使用它来修改 method_missing 以将上述方法转发到 user.manager?user.make_manager!

    【讨论】:

    • 除上述 Group 模型外,许多 ActiveRecord 模型都应用了不同的角色。将角色视为graph database 中的无向(互易)边。并非所有类型的节点都可以支持相同类型的边。
    • 虽然它们总是与用户的实例相关,但它们也通过多态关联与另一个类的实例相关
    猜你喜欢
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 2010-10-15
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多