0

将此示例用于文件上传器。

现在它是这样工作的:我上传一个文件,文件保存后,函数(do_picture_analysis)调用R并生成一个直方图(最简单的版本,在更复杂的版本2包必须安装在R中),图片直方图被保存。问题是,如果我想上传 50 个文件,在 R 中分别为每个文件加载 2 个包需要花费大量时间(after_save 回调)。

我需要什么:我上传一个文件,保存文件,单击“直方图”按钮,然后对数据库中的所有文件调用 do_picture 分析函数(如果某些文件已经分析过,则无关紧要)

所以我只需要知道如何在按钮和函数调用之间进行交互,仅此而已。

我的 show.html.erb:

<script id="template-download" type="text/x-tmpl">
  {% for (var i=0, file; file=o.files[i]; i++) { %}
    <tr class="template-download fade">

       <td></td>
      <td class="name">
       <a href="{%=file.url%}" download="{%=file.name%}">{%=file.name%}</a>
      </td>
       <td class="nam">
       <a href="{%=file.url_chip_image%}" download="{%=file.name%}">{%=file.name%}</a>
      </td>


      <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>     

      <td class="Pic">
        <button class="btn btn-mini btn-info">Pic</button>    
      </td>

      <td class="Hist">
        <button class="btn btn-mini btn-primary" >Hist</button>        
      </td>

      <td class="delete">
        <button class="btn btn-mini btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}"> 
          <i class="icon-trash icon-white"></i>

        </button>
        <input type="checkbox" name="delete" value="1">
      </td>
    </tr>
    {% } %}
</script>

我的上传.rb:

def to_jq_upload
    {
      "name" => (read_attribute(:upload_file_name)).split(".").first,
      "size" => read_attribute(:upload_file_size),
      "url" => upload.url(:original),
      "delete_url" => upload_path(self),
      "delete_type" => "DELETE",
      "url_chip_image"=>read_attribute(:chip_image),

    }
  end


  after_save :do_picture_analyse


def do_picture_analyse
  if read_attribute(:chip_image)==nil

   require 'rinruby'
    myr = RinRuby.new(echo=false)

myr.filepath=upload.path(:original)
myr.fileurl=upload.url(:original)


myr.eval <<EOF
   s=read.table(filepath)
   for(j in nchar(filepath):1){
         if(substr(filepath,j,j)=="/"){      
           savepath<-substr(filepath,1,j-1)
           file.name<-filepath
           file.name<-substr(file.name,j+1,nchar(filepath)-4)

           break
         }
       }


  file.name1<-paste(file.name,"image.jpeg",sep="_")
  savepath<-paste(savepath,file.name1,sep="/")

   jpeg(filename=savepath,width=250, height=250)
   hist(s$V1) 
   dev.off()




EOF



  self.update_attributes(
    :chip_image => (((myr.fileurl).split("?").first)[6..-5]+'_image.jpeg')
  )
end

end

编辑:

do_picture_analysis 可以将一个文件夹作为参数,并通过只为整个文件夹加载一次包来分析其中的所有文件。文件只有两个文件夹(两种不同类型的文件,比如说 .txt 和 .blabla 文件将保存在 txt-Folder 或 blabla-Folder 中。文件夹的类型也保存在数据库中。通过单击按钮,应将两个文件夹传递给 do_picture_analysis ,它将完成所有工作 提前致谢

4

2 回答 2

1

您需要为此创建一条新路线:

resources :name_of_your_controller do
  # use this if you want a route like resources/:id/analyze (single file)
  get :analyze, on: :member 
  # use this if you want a route like resources/analyze (multiple files)      
  get :analyze, on: :collection
end

然后在您的控制器上创建一个新操作:

def analyze
  # for single file analysis do something like this :
  @file = File.find( params[:id] )
  @file.do_picture_analyse
  respond_to do |format|
    # render what you need to render, js or html
  end

  # ... or do something like this for multiple file analysis :
  @files = File.where( params[:search] )
  @files.each {|f| f.do_picture_analyse )
  # etc.
end

然后,您可以将按钮链接到您的操作:

# single file
<%= link_to "Histogram", analyze_file_path( file ) %>
# multiple files
<%= link_to "Histogram", analyze_files_path( search: your_search_conditions ) %>

PS:如果您的方法需要大量处理能力(如果您使用 R,我假设您涉及复杂的计算),您应该考虑将其提取到Worker中以将其作为后台任务运行。

编辑

回复您的评论:

我认为您应该提取此方法并使其成为接受一个或多个路径的类方法。然后创建一个指向你的控制器的集合路由;在您的控制器操作中,根据一些参数加载文件并执行以下操作:

# find the directories to be processed : 
paths = @files.map(&:folder_type).uniq
# pass them to your class method : 
File.do_picture_analyse(paths)

甚至可以创建一个类方法来自动处理关系中所有文件的这两个步骤:

def self.perform_analysis!
  paths = all.map(&:folder_type).uniq # or uniq.pluck(:folder_type) on rails >= 3.2.1
  do_picture_analyse(paths)
end

def self.do_picture_analyse( *paths )
  # call R from here
end

那么你可以这样做:

File.where( your_search_params ).perform_analysis!
于 2012-12-01T13:40:54.917 回答
1

简短而甜蜜的答案:在您的文章中show.html.erb

  <td class="Hist">
    <%= link_to 'Histogram', histogram_path, ;method => :post, :class => 'btn btn-mini btn-primary" %>
  </td>

在您config/routes.rb添加以下行

post '/histogram' => 'your-controller#histogram', :as => 'histogram'

这意味着histogram_path将指向一个名为your-controller并调用 action的控制器histogram请用你的名字替换那些。

然后你应该很高兴。

我冒昧地提出了一个 POST 动作,因为我假设该动作不是幂等的。如果是,您应该使用 GET。

希望这可以帮助。

于 2012-12-01T15:46:10.240 回答