2016-01-01 20 views
2

因此,我有幾個控制器與模型實例列表一起工作,一旦我完成了一個控制器,我決定將其全部考慮在內只是重用代碼。控制器中的關注/混入 - 使用變量/方法的可見性

module ListController 
    extend ActiveSupport::Concern 
    #code 
end 

但它給我帶來了幾個問題。

首先,我需要這個控制器來處理不同的資源。例如:

module ListController 
    extend ActiveSupport::Concern 
    included do 
    doll = self.name.to_s.match(/^(\w+)ListController/)[1] 
    @resource = doll.downcase 
    @klass = doll.singularize.constantize 
    define_method("new_#{@resource}_list") do 
     if appropriate_quantity? 
     quantity=params[:quantity].to_i 
     array = Array.new(quantity) do 
      @klass.new 
     end 
     instance_variable_set("@#{@resource}", array) 
     elsif invalid_entry_cookie? 
     invalid_entries_from_redis(@klass) 
     else 
     redirect_to :back 
     end 
    end 
    end 
end 

所以,當包含模塊,我得到控制器的名稱,ListController之前發現的一部分,通過我自己的約定,它使我需要的型號和資源:

doll = self.name.to_s.match(/^(\w+)ListController/)[1]#=>Students 
@resource = doll.downcase #=>students 
@klass = doll.singularize.constantize #=>Student 

似乎對人好點。但是

1)模塊本身沒有看到實例變量。所以@resource@klass鬆開它在行define_method後的可見性,並且一切都失去了它的意義。我無法讓模塊具有足夠的靈活性,以便在沒有這些變量的情況下可以重複使用,從而始終可以看到包含的塊解?

2)與包括,我通過@resource@klass到每個控制器?我不喜歡這個,因爲他們只是不需要那裏。我想避免它。

回答

0

1)您可以使用before_action過濾器來設置這些實例變量如下:

module ListController 
    extend ActiveSupport::Concern 

    included do 

    # Set instance vars in the current class 
    init_proc = Proc.new do |c| 
     doll = c.class.name.match(/^(\w+)ListController/)[1] 
     c.instance_variable_set(:@resource, doll.downcase) 
     c.instance_variable_set(:@klass, doll.singularize.constantize) 
    end 

    # Run the above proc before each page load this method is declared in 
    before_action(init_proc) 

    # Make @resource and @klass available right now 
    init_proc.call(self) 

    define_method("new_#{@resource}_list") do 
     if appropriate_quantity? 
     quantity=params[:quantity].to_i 
     array = Array.new(quantity) do 
      @klass.new 
     end 
     instance_variable_set("@#{@resource}", array) 
     elsif invalid_entry_cookie? 
     invalid_entries_from_redis(@klass) 
     else 
     redirect_to :back 
     end 
    end 
    end 
end 

2)您可以在ApplicationController這樣的擔心,避免包括無處不在。