2013-11-19 2 views
0

Я собрал два образца классов, реализованных несколькими способами, которые довольно хорошо отражают то, что я хочу сделать в моей модели Rails. Меня беспокоит, что я не знаю, что, если есть проблемы с использованием любого метода. И я только нашел сообщения, которые объясняют, как их реализовать, или общее предупреждение, чтобы избежать/быть осторожным при их использовании. То, что я не нашел, - это ясное объяснение того, как это сделать безопасно, и о том, что я забочусь о том, почему я должен избегать этого шаблона.Динамические методы, использующие define_method и eval

class X 
    attr_accessor :yn_sc, :um_sc 
    def initialize 
    @yn_sc = 0 
    @um_sc = 0 
    end 
    types = %w(yn um) 
    types.each do |t| 
    define_method("#{t}_add") do |val| 
     val = ActiveRecord::Base.send(:sanitize_sql_array, ["%s", val]) 
     eval("@#{t}_sc += #{val}") 
    end 
    end 
end 

class X 
    attr_accessor :yn_sc, :um_sc 
    def initialize 
    @yn_sc = 0 
    @um_sc = 0 
    end 
    types = %w(yn um) 
    types.each do |t| 
    # eval <<-EVAL also works 
    self.class_eval <<-EVAL 
     def #{t}_add(val) 
     @#{t}_sc += val 
     end 
    EVAL 
    end 
end 


x = X.new 
x.yn_add(1) #=> x.yn_sc == 1 for both 

ответ

1

Ну, ваш код выглядит реально безопасным. Но представьте код, основанный на пользовательском вводе. Это может быть что-то вроде выглядеть

puts 'Give me an order, sir!' 
order = gets.chomp 
eval(order) 

Что произойдет, если наш капитан будет идти дикий и заказ нам на 'rm -rf ~/'? Грустные вещи наверняка!

Итак, сделайте небольшой урок. eval небезопасен, потому что он оценивает каждую полученную строку. Но есть и другая причина: не использовать eval. Иногда он оценивается медленнее, чем альтернативы. Посмотрите here если заинтересованы.

+0

Ну, 'val' будет вводиться пользователем из формы, хотя я знаю, что есть способы, которыми вредоносный пользователь может обманывать это, следовательно,« санизировать ». – MCB