2017-12-28 22 views
0

RubyでCSVインポータをプログレスバーで作成しようとしています。問題は、SiteControllerは、ProgressBarの変数が初期化されていないことを示しています。どうやってそれを正しくすることができますか?私はコントローラ内の変数にアクセスできる必要があります。しかし、インクルードを使ってうまく動作しないのはなぜですか?ファイル間のRuby共有変数

class SpecificImporter < Importer 

    include ProgressBar 
    def import 
     .... 
     custom logic 
     Thread.new do 
     @rows.each do |r| 
     increment_bar 
     end 
    end 
end 

class Importer 
    attr_accessor :file 
    include ProgressBar 

    def calculate_max_rows 
     l = File.open(@file.path).count 
     set_max_rows(l) 
    end 
end 

module ProgressBar 
    attr_reader :cur,:max 

    def increment_bar 
     @cur += 1 
    end 
    def set_max_rows(val) 
     @max = val 
    end 

    def progress 
     @cur/@max 
    end 

end 

class SiteController < ApplicationController 
    include ProgressBar 
    def update_progress 
     .. 
     #send data using json every x seconds 
     .. 
     status = progress 
    end 

end 
+3

注意親クラスがすでにそれを行っているので、 'SpecificImporter'が' ProgressBarをインクルードする '必要はないはずです。 – tadman

+1

さらに、 'set_max_rows'のようなものはRubyの精神に反するものです。その属性に書き込めるようにするには、 'max ='メソッドを与える 'attr_accessor'を使います。わかりやすくするために、その属性を 'max_rows'と呼んで、代わりに' self.max_rows = l'を行うことができます。 – tadman

答えて

0

モジュールは単なる方法と変数です。 ImporterクラスとSiteControllerの間で使用できるストレージは提供していません。お互いに継承されていない複数のクラスで等しいメソッドを定義する機能を提供するだけです。それはMixinパターンのようなものです(この説明を見てください:https://en.wikipedia.org/wiki/Mixin)。

"ファイル間で変数を共有する"には、RedisまたはMemcachedと同様のものを使用する必要があります。 =通常のSQL DBは、あまりにもこの機能を提供することができますが、それは、この場合、それほど効果的ではありません)

それが動作するはず方法を理解するために、このガイドを見てみましょう:https://www.sitepoint.com/introduction-to-using-redis-with-rails/

ので、ここで少しですあなたの例の改善は、それを明確に(もっとよりよい解決策は、Redisの中でカウンターを実装するか、それはRedisの上の負荷を減少させるので、すべての10のステップで値だか更新するだろう。しかし、それは合併症です。)作るために):

module ProgressBar 
    attr_accessor :curr, :max 

    def increment_bar 
    @curr += 1 
    save_progress # <- Save progress on each step 
    end 

    def progress 
    @curr/@max 
    end 

    def save_progress(process_id) 
    $redis.set("progress_#{process_id}", progress) 
    end 

    def load_progress(process_id) 
    $redis.get("progress_#{process_id}") || 0 
    end 
end 

class Importer 
    include ::ProgressBar 

    def calculate_max_rows 
    # some logic will go here... 
    set_max_rows(l) 
    end 
end 

class SpecificImporter < Importer 
    def import 
    # custom logic... 
    increment_bar 
    end 
end 

class SiteController < ApplicationController 
    include ProgressBar 
    def update_progress 
    # some logic here... 
    status = load_progress(params[:process_id]) # <- Load stored progress 
    end 
end 
関連する問題