2011-12-20 53 views
0

我在我的應用程序中有一個bazillion控制器,我想知道如何使用一些元編程來使維護更少。這是有效的,但它的eval形式的危險刺激:Eval alternative

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 
+0

[decent_exposure](https://github.com/voxdolo/decent_exposure)gem可能會讓你成爲那裏的一部分,儘管它不會完全解決問題。 – 2011-12-20 12:08:03

回答

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 
+0

哦,這很方便。但是,我需要能夠設置實例變量。我會用期望的結果編輯我的問題。謝謝! – snowangel 2011-12-20 09:31:20

+0

@snowangel - 它看起來像'instance_variable_set' _應該做你想做的。我會編輯我的答案 - 但你說你已經試過了? – Chowlett 2011-12-20 09:36:29

+0

嗯,我試過了,但可能做錯了,所以你的想法會非常有幫助。 – snowangel 2011-12-20 09:39:23

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 
+0

這會引發錯誤「不允許書籍作爲實例變量名稱」。 Chowlett的版本雖然工作。非常感謝答覆! – snowangel 2011-12-20 09:44:26

0

你想使用inherited_resource寶石做這一切的嗎?

+0

聽起來很蠢,但是由於寶石的依賴關係,我的heroku slu size大小已經是77mb了。我儘可能不要添加更多! – snowangel 2011-12-20 15:11:01

+0

我認爲Heroku將不得不重新評估100MB的限制。我的基本Rails 3.1應用程序也接近50MB。我寧願讓Heroku解決這個問題,而不是擺脫我的寶石。 – Amala 2011-12-20 18:17:41

+0

我同意。我最近爲他們發佈了一個支持票 - 如果我聽到回覆,會在這裏添加評論。 – snowangel 2011-12-21 06:16:07