Эта ошибка возникает, когда вы определяете класс внутри метода другого класса.то есть вы, вероятно, делали что-то вроде ниже:
class SomeClass
def some_method
class Hash
def sort_by_array(a)
end
end
end
end
Предполагая, что вы хотите расширить функциональность Hash
объектов, добавив метод sort_by_array
, тогда вы можете выполнить патч обезьяны, как показано ниже:
Решение (Простое):
- Вы можете определять только методы «экземпляра».Если вы хотите определить также методы «класса», см. «Расширенное» решение ниже.
lib / extensions / hash.rb
module Extensions
module Hash
def sort_by_array(a)
sort_by do |k, _|
a.index(k) || length
end
end
end
end
то есть, скажем, другой класс, который вы хотите расширить функциональность:
lib / extensions / active_record / base.rb
module Extensions
module ActiveRecord
module Base
def say_hello_world
puts 'Hello World!'
end
end
end
end
config/initializers/extensions.rb
Hash.include Extensions::Hash
ActiveRecord::Base.include Extensions::ActiveRecord::Base
Использование:
# rails console
some_array = [:a, :c, :b]
some_hash = { a: 1, b: 2, c: 3 }
some_hash.sort_by_array(some_array)
# => [[:a, 1], [:c, 3], [:b, 2]]
user = User.find(1)
user.say_hello_world
# => 'Hello World!'
Решение (Advanced):
- теперь разрешает как "класс", так иМетоды «instance», которые будут определены:
lib / extensions / hash.rb
module Extensions
module Hash
def self.included(base)
base.extend ClassMethods
base.include InstanceMethods
end
# define your Hash "class methods" here inside ClassMethods
module ClassMethods
# commented out because not yet fully working (check update later)
# # feel free to remove this part (see P.S. for details)
# def self.extended(base)
# instance_methods.each do |method_name|
# raise NameError, "#{method_name} method already defined!" if (base.singleton_methods - instance_methods).include? method_name
# end
# end
end
# define your Hash "instance methods" here inside InstanceMethods
module InstanceMethods
# commented out because not yet fully working (check update later)
# # feel free to remove this part (see P.S. for details)
# def self.included(base)
# instance_methods.each do |method_name|
# raise NameError, "#{method_name} method already defined!" if (base.instance_methods - instance_methods).include? method_name
# end
# end
def sort_by_array(a)
sort_by do |k, _|
a.index(k) || length
end
end
end
end
end
т.е. скажем, другой класс, который вы хотитерасширить функциональность:
lib / extensions / active_record / base.rb
module Extensions
module ActiveRecord
module Base
def self.included(base)
base.extend ClassMethods
base.include InstanceMethods
end
module ClassMethods
# commented out because not yet fully working (check update later)
# # feel free to remove this part (see P.S. for details)
# def self.extended(base)
# instance_methods.each do |method_name|
# raise NameError, "#{method_name} method already defined!" if (base.singleton_methods - instance_methods).include? method_name
# end
# end
def say_hello_mars
puts 'Hello Mars!'
end
end
module InstanceMethods
# commented out because not yet fully working (check update later)
# # feel free to remove this part (see P.S. for details)
# def self.included(base)
# instance_methods.each do |method_name|
# raise NameError, "#{method_name} method already defined!" if (base.instance_methods - instance_methods).include? method_name
# end
# end
def say_hello_world
puts 'Hello World!'
end
end
end
end
end
config / initializers / extensions.rb
Hash.include Extensions::Hash
ActiveRecord::Base.include Extensions::ActiveRecord::Base
Использование:
# rails console
some_array = [:a, :c, :b]
some_hash = { a: 1, b: 2, c: 3 }
some_hash.sort_by_array(some_array)
# => [[:a, 1], [:c, 3], [:b, 2]]
user = User.find(1)
user.say_hello_world
# => 'Hello World!'
ActiveRecord::Base.say_hello_mars
# => 'Hello Mars!'
PS, возможно, вам не нужно будет выдавать ошибку, если метод уже определен, но это мой личный вкус предотвратить"ошибки" (то есть, если, например, некоторые "драгоценные камни", которые вы использовали, также определилиодно и то же точное имя метода, но с другой функциональностью, которую вы не можете контролировать).Не стесняйтесь их удалять.