[英]No method error for class variable defined with attr_accessor
I want to define methods dynamically using an array of strings. 我想使用字符串数组动态定义方法。
Here is a simple piece of code that should achieve that. 这是应该实现的简单代码。
class SomeClass
attr_accessor :my_array
def initialize(user, record)
@my_array=[]
end
my_array.each do |element|
alias_method "#{element}?".to_sym, :awesome_method
end
def awesome_method
puts 'awesome'
end
end
When I instantiate this class in the console, I get the following error 当我在控制台中实例化此类时,出现以下错误
NoMethodError (undefined method `each' for nil:NilClass) NoMethodError(nil:NilClass的未定义方法“ each”)
What is wrong with this code and how to make it work. 此代码有什么问题,以及如何使其工作。 any help highly appreciated :) 任何帮助,高度赞赏:)
Edit 1: What I ultimately want to achieve is to inherit from SomeClass and override my_array in the child class to dynamically define methods with its attributes like so 编辑1:我最终想要实现的是从SomeClass继承并覆盖子类中的my_array以动态定义具有其属性的方法,如下所示
class OtherClass < SomeClass
my_array = %w[method1 method2 method3]
# Some mechanism to over write my_array.
end
And then use self.inherited
to dynamically define methods in child class. 然后使用self.inherited
动态定义子类中的方法。
Is there a good way to achieve this? 是否有实现此目标的好方法?
In your code, you use an instance variable (@my_array) and an attr_accessor over it, and then try to access my_array from class level (that is, from the body of the class definition, outside of any methods). 在代码中,您使用实例变量(@my_array)和其上的attr_accessor,然后尝试从类级别(即从任何方法之外的类定义的主体)访问my_array。 But instance variables only exist at instance level, so it is not available in the class scope. 但是实例变量仅存在于实例级别,因此在类范围中不可用。
One solution (the natural one, and the one which you would probably use in other languages) is to use a class variable: @@my_array. 一种解决方案(自然的解决方案,以及您可能会用其他语言使用的解决方案)是使用类变量:@@ my_array。 But class variables in ruby are a little problematic, so the best solution would be to make use of class instance variables, like that: 但是ruby中的类变量有点问题,因此最好的解决方案是利用类实例变量,如下所示:
class SomeClass
class << self
attr_accessor :my_array
end
@my_array=[]
def initialize(user, record)
end
@my_array.each do |element|
alias_method "#{element}?".to_sym, :awesome_method
end
def awesome_method
puts 'awesome'
end
end
The syntax is a little tricky, so, if you look that up and it still doesn't makes sense, try just reading about scopes and using a regular class variable with @@. 语法有点棘手,因此,如果您查找起来仍然没有意义,请尝试仅阅读范围并使用带有@@的常规类变量。
Edit: 编辑:
Ok, so, after your edit, it became more clear what you are trying to accomplish. 好的,因此,在您进行编辑之后,您将要完成的任务变得更加清晰。 A full working example is like follows: 完整的工作示例如下:
class SomeClass
class << self
attr_accessor :my_array
end
@my_array=[]
def awesome_method
puts 'awesome'
end
def self.build!
@my_array.each do |element|
self.define_method("#{element}?".to_sym){ awesome_method }
end
end
end
class ChildClass < SomeClass
@my_array = %w[test little_test]
self.build!
end
child_instance = ChildClass.new
child_instance.test?
>> awesome
child_instance.little_test?
>> awesome
So, I've made some tweaks on SomeClass: 因此,我对SomeClass进行了一些调整:
With that done, ChildClass inherits from SomeClass, and it's instances have the dynamically created methods 'test?' 完成后,ChildClass继承自SomeClass,并且其实例具有动态创建的方法“ test?”。 and 'little_test?'. 和“ little_test?”。
You need to change my_array
to class level accessible, in my case class constant. 您需要将my_array
更改为可访问的类级别,在本例中为类常量。
class SomeClass
DYNAMIC_METHOD_NAMES = %w(method_a method_b method_C).freeze
def initialize(user, record)
end
DYNAMIC_METHOD_NAMES.each do |element|
alias_method "#{element}?".to_sym, :awesome_method
end
def awesome_method
puts 'awesome'
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.