Ruby on rails 如何从实例方法访问传递给acts_as插件(ActiveRecord decorator)的选项?

Ruby on rails 如何从实例方法访问传递给acts_as插件(ActiveRecord decorator)的选项?,ruby-on-rails,ruby,ruby-on-rails-plugins,Ruby On Rails,Ruby,Ruby On Rails Plugins,目前,我将每个选项存储在它自己的class属性中,但当我需要从实例方法访问传递的选项时,这会导致代码难以读取 例如,如果我将列名作为选项传递,我必须使用self.send(self.class.path\u finder\u column)从实例方法获取列值 注意,我在class属性前面加上了插件的名称,以防止名称冲突 下面是一个插件的简单代码示例,它被传递了一个选项,列,然后从实例方法set\u path访问该选项。能否将getter/setter简化为更具可读性 # usage: path_

目前,我将每个选项存储在它自己的class属性中,但当我需要从实例方法访问传递的选项时,这会导致代码难以读取

例如,如果我将列名作为选项传递,我必须使用
self.send(self.class.path\u finder\u column)
从实例方法获取列值

注意,我在class属性前面加上了插件的名称,以防止名称冲突

下面是一个插件的简单代码示例,它被传递了一个选项,
,然后从实例方法
set\u path
访问该选项。能否将getter/setter简化为更具可读性

# usage: path_find :column => 'path'

module PathFinder    
  def path_finder(options = {})
    send :include, InstanceMethods

    # Create class attributes for options 
    self.cattr_accessor :path_finder_column
    self.path_finder_column = options[:column]

    module InstanceMethods
      def set_path        
        # setter
        self.send(self.class.path_finder_column + '=', 'some value')
        # getter
        self.send(self.class.path_finder_column)
      end
    end
  end 
end

ActiveRecord::Base.send :extend, PathFinder

您可以使用cattr_访问器在类级别存储配置值,并在所有实例方法中使用。你可以在网站上看到一个例子

要查看的代码如下所示:

def acts_as_permalinkable(options = {})
          send :cattr_accessor, :permalink_options
          self.permalink_options = { :permalink_method => :name, :permalink_field_name => :permalink, :length => 200 }
          self.permalink_options.update(options) if options.is_a?(Hash)

          send :include, InstanceMethods
          send :after_create, :generate_permalink
        end

希望有帮助

首先,cattr_访问器为给定的每个符号创建一个类变量。在ruby中,类变量的名称前缀为@@

因此,您可以使用
@@path\u finder\u column
代替
self.class.path\u finder\u column

然而,考虑到我接下来的建议,这是一个没有实际意义的观点

在问题代码中提出的具体案例中。您定义的getter和setter组合不符合ruby约定。鉴于您实际上是如何用一个通用名称重新命名为path\u finder\u列生成的访问器,您可以将其全部简化为一对别名

假设combo访问器中存在错误(代码应该如何知道是获取还是设置),最终确定的模块将如下所示:

module PathFinder    
  def path_finder(options = {})
    send :include, InstanceMethods

    # Create class attributes for options 
    self.cattr_accessor :path_finder_column
    self.path_finder_column = options[:column]
    alias :set_path, path_finder_column
    alias :set_path=, "#{path_finder_column}="
  end

  module InstanceMethods  
    # other instance methods here.
  end
end

您可以在运行时生成所有这些方法

module PathFinder
  def path_finder(options = {})

    # Create class attributes for options 
    self.cattr_accessor :path_finder_options
    self.path_finder_options = options

    class_eval <<-RUBY
      def path_finder(value)
        self.#{options[:column]} = value
      end

      def path_finder
        self.#{options[:column]}
      end
    RUBY
  end
end

ActiveRecord::Base.send :extend, PathFinder
请注意,我的解决方案不需要setter和getter,只要始终使用
path\u finder
path\u finder=
。 因此,最短的解决方案是(假设只有:列选项,没有其他要求)

模块探路器
def path_查找器(选项={})
#这里有更多的逻辑
# ...

class_eval-1:问题中发布的代码已经使用了cattr_访问器。
self.cattr_accessor :path_finder_options
self.path_finder_options = options
module PathFinder
  def path_finder(options = {})

    # here more logic
    # ...

    class_eval <<-RUBY
      def path_finder(value)
        self.#{options[:column]} = value
      end

      def path_finder
        self.#{options[:column]}
      end
    RUBY
  end
end

ActiveRecord::Base.send :extend, PathFinder