使用Ruby中的eval函数调用其他函数

时间:2022-08-24 14:56:45

I'm using below class with processQuestion function to call other methods.

我在下面用processQuestion函数来调用其他方法。

This function is called by calling CONSTANTS of other classes.

这个函数通过调用其他类的常量来调用。

# Is responsible for executing a particular question. Question types are in the Question object. A question will 
# always have a responding method in this class. That method will take the parameters defined by the question and
# should provide the answer in the format expected.
class QuestionProcessor
  NO_ROUTE = "NO SUCH ROUTE"

  def initialize(routeList)
    @routeList = routeList
  end


  # Finds the method and runs it. This should provide the answer object
  def processQuestion(question)
    return eval("get"+question.command+"(question)")
  end


  # Finds the total distance using the exact stations specified, or returns NO_ROUTE if no route was stored in the route list
  # this method ignores the constraints and actions
  def getDistance(question)
    distance = 0
    currentStation = nil

    question.parameters.each do |nextStation|
      if (! currentStation.nil?)
        route = @routeList.getDirectRoute(currentStation, nextStation)
        if (route.nil?)
          return NO_ROUTE
        end
        distance += route.distance
      end
      currentStation = nextStation;
    end

    return distance;
  end


  # Finds the shortest route possible for the given constraint. This method requires a constraint and action to be provided
  def getShortestRoute(question)
    startStation = question.parameters[0]
    endStation = question.parameters[1]

    routeProcessor = ShortestRouteProcessor.new(@routeList, question.constraint, question.action)
    routeProcessor.getRoute(startStation, endStation)

    return routeProcessor.shortestRoute == Constants::INTEGER_MAX ? NO_ROUTE : routeProcessor.shortestRoute
  end


  # Counts the number of routes based on the condition provided. Intended to count the number of routes, but could potentially provide a total distance
  # or anything else produced by the action.
  def getCountRoutes(question)
    startStation = question.parameters[0]
    endStation = question.parameters[1]

    routeProcessor = RouteProcessor.new(@routeList, question.constraint, question.action)
    routeProcessor.getRoute(startStation, endStation)

    return routeProcessor.totalSuccessfulRoutes 
  end
end

I thought this is a good approach to remain DRY but I hear eval is evil.

我认为这是保持干燥的好方法,但我听说eval是邪恶的。

Is this good approach or should I look for other ways in a more object oriented way?

这是一种好方法,还是我应该以一种更面向对象的方式寻找其他方法?

2 个解决方案

#1


3  

In this case you may safely use send instead of eval, like in this example:

在本例中,您可以安全地使用send而不是eval,例如在本例中:

def processQuestion(question)
  return send("get#{question.command}", question)
end

Just be aware that send may be as dangerous as eval if you do not sanitize your input (question.command in this case).

只要注意,如果不清理输入(在本例中是question.command),那么send可能与eval一样危险。

If possible, do a white-list filtering before calling send (or eval), otherwise someone could pass a command which does something you do not want to do.

如果可能的话,在调用send(或eval)之前进行白名单过滤,否则有人可能会传递一个命令,这个命令执行一些您不希望执行的操作。

#2


3  

There is a function in ruby for exactly this reason, the send function. It is part of the Object class so everything has it.

ruby中有一个函数正是因为这个原因,发送函数。它是对象类的一部分,所以所有东西都有它。

read more here: http://ruby-doc.org/core-2.1.1/Object.html#method-i-send

阅读更多:http://ruby-doc.org/core-2.1.1/Object.html method-i-send

for metaprogramming I recommend you read this whole tutorial: https://rubymonk.com/learning/books/2-metaprogramming-ruby/

对于元编程,我建议您阅读本教程:https://rubymonk.com/learning/books/2-metaprogram-ruby/

#1


3  

In this case you may safely use send instead of eval, like in this example:

在本例中,您可以安全地使用send而不是eval,例如在本例中:

def processQuestion(question)
  return send("get#{question.command}", question)
end

Just be aware that send may be as dangerous as eval if you do not sanitize your input (question.command in this case).

只要注意,如果不清理输入(在本例中是question.command),那么send可能与eval一样危险。

If possible, do a white-list filtering before calling send (or eval), otherwise someone could pass a command which does something you do not want to do.

如果可能的话,在调用send(或eval)之前进行白名单过滤,否则有人可能会传递一个命令,这个命令执行一些您不希望执行的操作。

#2


3  

There is a function in ruby for exactly this reason, the send function. It is part of the Object class so everything has it.

ruby中有一个函数正是因为这个原因,发送函数。它是对象类的一部分,所以所有东西都有它。

read more here: http://ruby-doc.org/core-2.1.1/Object.html#method-i-send

阅读更多:http://ruby-doc.org/core-2.1.1/Object.html method-i-send

for metaprogramming I recommend you read this whole tutorial: https://rubymonk.com/learning/books/2-metaprogramming-ruby/

对于元编程,我建议您阅读本教程:https://rubymonk.com/learning/books/2-metaprogram-ruby/