Eval替代品

时间:2011-12-20 09:18:47

标签: ruby-on-rails ruby metaprogramming

我的应用程序中有一个bazillion控制器,我想知道如何使用一些元编程来减少维护。这有效,但它以eval的形式飙升危险:

  def plural_action(method_name)
    class_name =  self.class.to_s.gsub( %r{^(\w*)Controller} ) {|s| $1 } 
    @title = "#{method_name.to_s.titlecase} of #{class_name}" 
    eval "@q = #{class_name.singularize}.where(:client_id => current_user.client_id).search(params[:q])"
    eval "@#{class_name.downcase} = @q.result(:distinct => true).paginate(:page => params[:page])"
    eval "session[:query] = @#{class_name.downcase}.map(&:id)"
    eval "respond_with(@#{class_name.downcase})" 
  end

我可以不使用eval吗?我已经修改了instance_variable_set,send和const_get但到目前为止没有运气。

这是我想要评估方法的一个例子。

  def index
    @title = "Index of Books" 
    @q = Book.where(:client_id => current_user.client_id).search(params[:q])
    @books = @q.result(:distinct => true).paginate(:page => params[:page])
    session[:query] = @books.map(&:id)
    respond_with(@books)
  end

2 个答案:

答案 0 :(得分:3)

有一个宏观的方法constantize,它将一个字符串转换为它所代表的常量(其中类类型是一个例子)。考虑到这一点,我认为你可以将你的方法重写为:

def plural_action(method_name)
    class_name =  self.class.to_s.gsub( %r{^(\w*)Controller} ) {|s| $1 } 
    @title = "#{method_name.to_s.titlecase} of #{class_name}" 
    @q = class_name.singularize.constantize.where(:client_id => current_user.client_id).search(params[:q])
    self.instance_variable_set("@#{class_name.downcase}", @q.result(:distinct => true).paginate(:page => params[:page]))
    session[:query] = self.instance_variable_get("@#{class_name.downcase}").map(&:id)
    respond_with(self.instance_variable_get("@#{class_name.downcase}"))
end

答案 1 :(得分:0)

def plural_action(method_name)
    class_name =  self.class.to_s.gsub( %r{^(\w*)Controller} ) {|s| $1 } 
    @title = "#{method_name.to_s.titlecase} of #{class_name}" 
    @q = class_name.singularize.constantize.where(:client_id => current_user.client_id).search(params[:q])
    instance_variable_set class_name.downcase, @q.result(:distinct => true).paginate(:page => params[:page])
    session[:query] = @q_result.map(&:id)
    respond_with(@q_result)
end