#ruby-on-rails #ruby
#ruby-on-rails #ruby
Вопрос:
Я хочу создать функцию для установки переменной экземпляра, например attr_reader
class Base
def exec
# get all functions to check
# if all functions return true
# I will do something here
end
end
И тогда у меня есть класс inherit Base
.
class SomeClass < Base
check :check_1
check :check_2
def check_1
# checking
end
def check_2
# checking
end
end
class Some2Class < Base
check :check_3
check :check_4
def check_3
# checking
end
def check_4
# checking
end
end
Поскольку мне нужна только 1 логика для выполнения во всех классах, но у меня много разных проверок для каждого класса, мне нужно делать это гибко.
Пожалуйста, дайте мне ключевое слово для этого.
Большое спасибо.
Ответ №1:
Для того, чтобы иметь check :check_1
, вам нужно определить check
как метод класса:
class Base
def self.check(name)
# ...
end
end
Поскольку вы хотите вызвать переданные имена методов позже, я бы сохранил их в массиве: (предоставляется другим методом класса checks
)
class Base
def self.checks
@checks ||= []
end
def self.check(name)
checks << name
end
end
Это уже дает вам:
SomeClass.checks
#=> [:check_1, :check_2]
Some2Class.checks
#=> [:check_3, :check_4]
Теперь вы можете перемещаться по этому массиву изнутри exec
и вызывать каждый метод через send
. Вы можете использовать all?
, чтобы проверить, все ли они возвращают правдивый результат:
class Base
# ...
def exec
if self.class.checks.all? { |name| send(name) }
# do something
end
end
end
SomeClass.new.exec # doesn't do anything yet
Эта self.class
часть необходима, потому что вы вызываете метод класса checks
из метода экземпляра exec
.
Комментарии:
1. спасибо @stefan. Я нашел то, что хочу. Я использовал
class_variables
для этого2. @tai.groddy обратите внимание, что переменная класса (with
@@
) является общей для класса и его подклассов. Вероятно, вы хотите иметь переменную экземпляра класса (с@
как показано выше), чтобы каждый подкласс мог иметь свой собственный массив.