Метапрограммирование, необходимое для СУХОГО модуля? - PullRequest
0 голосов
/ 01 ноября 2011

Я использую код пространства имен в приложении в качестве упражнения. И под «упражнением» я подразумеваю полностью для развлечения. Предположим, что примеры ролей Performer и Manager представляют 2 из 20 ролей, которые должны быть определены вместе с вспомогательными методами.

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

Я мог бы высушить содержимое методов с помощью замыканий, но поскольку имена методов также следуют шаблону, будет ли метапрограммирование более логичным? Пример ruby ​​

Достаточно ли распространено метапрограммирование в 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

Ответы [ 2 ]

1 голос
/ 01 ноября 2011

Это достаточно часто, но то, будет ли оно обслуживаемым, больше связано с предоставленной вами документацией и мышлением разработчика.

В идеале, метапрограммирование исчезает в приложении и редконужно потрогать.Для этого он будет делать то же самое - делать специфичные для ролей мёды.Насколько вероятно, что само метапрограммирование нужно будет поддерживать?

Пока есть путь от "эй, откуда взялись эти функции?"к коду, который внедряет функциональность, я думаю, что это нормально, особенно потому, что «мета» этой функциональности очень ограничен по объему.name выглядит так, и убедитесь, что очевидно, какое имя метода он будет отображать, если это что-то отличное от простых альфа-символов.

0 голосов
/ 01 ноября 2011

Это выглядит действительно сложно, вы уверены, что нет более простого способа?

С одной стороны, более подходящим представляется STI (наследование одной таблицы) или обычное обычное наследование (если вы не используете активную запись):

user.type?(Manager) вместо manager?(user_id)

и

user.update_attributes(:type => 'Manager') вместо make_manager(user_id)

Если бы вы собирались заниматься метапрограммированием, я бы использовал его на этом этапе, чтобы изменить method_missing, чтобы перенаправить вышеуказанные методы в user.manager? и user.make_manager!.

...