2016-04-07 3 views
2

Предположим, мы хотим, чтобы кто-то написал свой собственный псевдослучайный метод. Как программирование. И мы хотим, чтобы вызвать ошибку каждый раз, когда они пытаются решить для встроенных функций в контекстномОтключение тасования и выборки в классе Array

До сих пор, это то, что я сделал:

ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed" 

methods_to_block = ["rand", "srand", "Random::rand", "Random::srand", 
"Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", 
"Array::shuffle", "Array::shuffle!", "Array::sample"] 

methods_to_block.each do |method| 
    eval 
    """ 
    def #{method} 
    raise ERROR_STRING_FOR_RANDOM 
    end 
    """ 
end 

Таким образом, он блокирует вкось, и они поднимают ошибка:

rand 
srand 
Random.new.rand(18) 

но он не работает с псевдослучайными методами массива. Например,

[1,2,3].shuffle! 

Работает. Почему это происходит и как его предотвратить?

ответ

2

Вы можете открыть класс и заменить методы, которые вы хотите отключить ...

class Array 
    ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed" 
    RANDOM_METHODS = [:shuffle, :shuffle!, :select] 
    def rajarshi_random_error 
    raise ERROR_STRING_FOR_RANDOM 
    end 
    RANDOM_METHODS.each do |m| 
    define_method(m) {|*args| rajarshi_random_error } 
    end 
end 
+0

:)) .............. ......... –

2

Ваш код получал ошибки

ArgumentError: wrong number of arguments (0 for 1..4) 

, но и для других подобных функций модуля вы можете просто определить методы, как

methods_to_block = ["rand", "srand","seed", "sample", "shuffle!", "shuffle!"] 

следует выглядеть

methods_to_block.each do |method| 
    define_method "#{method}" do 
    raise ERROR_STRING_FOR_RANDOM 
    end 
end 
#=> ["rand", "srand", "Random::rand", "Random::srand", "Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", "Array::shuffle", "Array::shuffle!", "Array::sample"] 

Теперь, если вы звоните в

> srand 
RuntimeError: Usage of built-in random generators is not allowed 

> rand 
RuntimeError: Usage of built-in random generators is not allowed 

надеюсь, что это поможет вам

Если вы хотите придерживаться Остаюсь ваш путь

ERROR_STRING_FOR_RANDOM = "Usage of built-in random generators is not allowed" 

methods_to_block = ["rand", "srand", "Random::rand", "Random::srand", 
"Random::seed", "Random::new", "Kernel::rand", "Kernel::srand", 
"Array::shuffle", "Array::shuffle!", "Array::sample"] 


methods_to_block.each do |method| 
if method.split("::").size > 1 && method.split("::").first != "Kernel" 
class_name = method.split("::").first 
method_name = method.split("::").last 
er = <<ER 
class #{class_name} 
def #{method_name} 
raise ERROR_STRING_FOR_RANDOM 
end 
end 
ER 
eval(er) 
else 
define_method "#{method}" do 
raise ERROR_STRING_FOR_RANDOM 
end 
end 
end 

Теперь вы можете получить все

> srand 
RuntimeError: Usage of built-in random generators is not allowed 

> rand 
RuntimeError: Usage of built-in random generators is not allowed 

> [2,3,4,5].shuffle 
RuntimeError: Usage of built-in random generators is not allowed 
0

Хорошо. Это работает:

class Array 
    undef_method :sample, :shuffle, :shuffle! 
end 

Использование операторов с разрешающей способностью было неправильной идеей для начала. Они просто создают константы внутри классов вместо переназначения методов

Аналогично, надлежащим образом отключить ранд и srand выглядит следующим образом:

module Kernel 
    undef_method :rand, :srand 
    class << self 
    undef_method :rand, :srand 
    end 
end 

class Random 
    undef_method :rand, :srand, :seed 
    class << self 
    undef_method :rand, :srand, :new 
    end 
end 
Смежные вопросы