Ruby on rails 如何从实例方法访问传递给acts_as插件(ActiveRecord decorator)的选项?
目前,我将每个选项存储在它自己的class属性中,但当我需要从实例方法访问传递的选项时,这会导致代码难以读取 例如,如果我将列名作为选项传递,我必须使用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_
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