Ruby on Rails的最佳实践 - 大控制器VS微控制器(Ruby on Rails Best

2019-06-17 18:10发布

我需要在Ruby on Rails的谁必须做很多事情最佳实践 ,特别是与控制器一些信息,所以,现在一个简单的“秀”的行动是达线。 我知道,这是不是真的好,我有它的特定代码。

下面是一个示例代码:

def show
    sound = Sound.find(params[:id])
    @xml_path = File.dirname(sound.file.path)
    s3 = AWS::S3.new(
        :access_key_id => 'XXX',
        :secret_access_key => 'XXX')
    @url = s3.buckets['dev'].objects[sound.file.path[1..-1]].url_for(:read, :expires => 10*60)

    if sound.id_job != 0 && sound.transcript_progress != 100
      @response = Savon.client("http://srap.php?wsdl").request(:avance) do
        soap.body = { 
         :Jeton => "abcdef",
         :ID_job => sound.id_job,
        }
      end
      @response = @response.to_hash
      @progress = @response[:avance][:avancement].to_s.split("#")[1]# ID_job received is formed like "OK#123", we keep "123"
      if @progress == "Termine"
         sound.transcript_progress = 100
      elsif @progress == "ERROR"
        flash.now[:alert] = "Oups, il semblerait que le fichier soit illisible, ou qu'il n'y ait rien a ecouter !"
      elsif @progress != "Queued"
        sound.transcript_progress  = @response[:avance_response][:avancement].to_s.split("#")[2].split("%")[0].to_i
      end
      sound.save
    end

    if sound.transcript_progress == 100 # If transcription finished
      # Get XML File URL on the FTP
      @xml_path = Savon.client("http://srap.php?wsdl").request(:donneResultat) do
      soap.body = { 
       :Jeton => "XXX",
       :FichierSon => sound.id_job
      }
      end

      # Parse XML Path URL on Kimsufi
      @xml_path = @xml_path.to_hash[:donne_resultat_transposition_response][:chemin_fichier].to_s.split("#")[2].to_s.split("/")[5]


      # Create local directory (/tmp/sounds) for XML Temp Save
      if ! File.directory?(Rails.root.to_s + '/tmp/sounds')
        Dir.mkdir(Rails.root.to_s + '/tmp/sounds')
      end
      # Get XML from FTP
      ftp=Net::FTP.new                                     
      ftp.connect("ftp.com", 21)                                                         
      ftp.login("XXX", "XXX")                
      if ftp.closed?
        flash.now[:alert] = "Oups, il semblerait qu'il y ait eu un problème ! Merci d'actualiser la page"
      else  
        ftp.passive = true
        ftp.chdir('results')
        ftp.getbinaryfile(@xml_path, Rails.root.to_s + '/tmp/sounds/' + @xml_path)
        ftp.close
      end

      # Send XML on S3
      s3 = AWS::S3.new(
        :access_key_id => 'XXX',
        :secret_access_key => 'XXX')
      @xml_new = (File.dirname(@sound.file.path) + '/' + File.basename(@xml_path))[1..-1]
      s3.buckets['dev'].objects[@xml_new].write(Pathname.new(Rails.root.to_s + '/tmp/sounds/' + @xml_path))
      @file = s3.buckets['dev'].objects[@xml_new].read()
    end


    # A lot of logic again, i've not did it yet

  end

正如你所看到的,我有很多的逻辑在这里,我有,检查是否转录是在如果不是,更新progress_bar(@ sound.transcript_progress),如果是的话,我首先要连接到SOAP动作来获得在XML路径,然后通过FTP获取XML,然后将其股票亚马逊S3(SOAP低劣,我必须重新分析所有的反应...)。

在我所有的动作控制器,我必须在S3 / SOAP / FTP连接,不会以相同的顺序..所以我我在考虑做一个类每一个,就像在C ++中,一个抽象。 我想要的东西做,我不在乎(很多),它是如何做。 但是,什么是与MVC的最佳做法? 我必须做出一个新的文件夹“类?” 一个新的控制器?

Answer 1:

这更是一个长篇评论 ,因为这说明你的困境的根源,但没有提供任何解决方案。

这个问题实际上是MVC的误解,其回报率普及引起的。

它是两个因素的影响,这是导致控制器的此内爆的组合:

  • 在一个方面,你有贫血模型 ,因为,而不是真正的模型层,采用RoR的ORM实例的集合。 其理由是,Rails的最初创建是一个快速原型(代扔掉的代码)的框架。 和原型正是活动记录是最好的。 使用脚手架,你可以很容易地生成现有数据库的活动记录的结构。

    但是,这会导致一些领域的业务逻辑在控制器中泄漏。

  • 在另一边,你有不存在的观点。 既然目标是原型,Rails的青睐除暴安良的意见,这实际上可以包含表示逻辑,通过将它们合并到控制器。 的,现在下落不明,观点是简单的模板,只是称“意见”代替。

    这就迫使控制器包含表示逻辑。

这两个因素将是这个原因,所以我很想断言,即回报率甚至不是MVC框架。 所得图案是实际上更接近模型-视图-演示 。 虽然它已被简化为点时它开始打破分离关注 。



Answer 2:

大多数你的逻辑并不在控制器的归属。 该控制器的责任是配合输入(HTTP请求及其参数),输出(你的观点)。 一切是应该在模型中实现的业务逻辑- Sound在你的情况下,它看起来像。 您的每一个的if块,例如,将是一个不错的人选来实现的实例方法Sound类。 如果你发现自己重用跨越各种型号代码(如AWS存储位),在实施这些模块 (下lib )和包括那些模型模块。



Answer 3:

它看起来像所有的应该重构到一个模型(或库模块),并分解成更小的功能。 这样做的最好的理由是,因为你可以设置的单元测试单独测试更小的部分。 该控制器只需要实例化模型和数据返回给浏览器。



文章来源: Ruby on Rails Best practices - Big Controller vs Small Controller