使用自定义功能包装许多rails属性

时间:2017-03-30 23:53:28

标签: ruby-on-rails ruby

我有许多具有属性的模型,我需要在阅读时应用一些新行为。我是Ruby / Rails的新手,所以我现在只是为一个属性定义一个getter并在其上面应用我的功能(类似于亵渎过滤的东西),但是我要去为一个很多的对象/属性做这个,并希望更清洁。

例如,对于Post对象的body属性,这就是我现在完成的方式:

class Post < ActiveRecord::Base
    include Replaceable

    #...

    # A key point is that we want to keep the original content in the db
    def body
        profanity_filter(self[:body])
    end
end

......我的担忧看起来像这样:

module Replaceable
    extend ActiveSupport::Concern

    def profanity_filter(content)
        # filter and update content...

        content
    end
end

这很有效,我很满意,除了现在我必须将它应用到整个应用程序的许多领域,而且我喜欢比在任何地方覆盖吸气剂更优雅的东西。

我调查了代表,以便我可以做一些像

这样的事情
delegate :body, :title, :etc, :to => :profanity_filter 

...但这不起作用,因为我无法传递需要过滤的内容。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

这是实现自己的类宏的最佳时机。

我将重用你的Replaceable模块来定义这个宏。

首先,让我们看看宏看起来像什么。

class Post < ActiveRecord::Base
  include Replaceable

  profanity_attrs :body, :foo, :bar, ...
end

然后我们实施它

module Replaceable
  extend ActiveSupport::Concern

  def profanity_filter(content)
    # filter and update content...

    content
  end

  # This module will be `extend`ed by the model classes
  module Macro
    def profanity_attrs(attributes)
      # Note the implicit `self` here refer to the model class
      attributes.each do |attr|
        class_eval do
          define_method(attr) do
            # Note the `self` here refer to the model instance
            profanity_filter(self[attr])
          end
        end
      end
    end
  end

  included do
    extend Macro
  end
end

P.S。我真的不知道profanity的含义,所以随意更改宏的名称:)