Ruby on Rails 最佳实践 - 大控制器与小控制器 [英] Ruby on Rails Best practices - Big Controller vs Small Controller

查看:25
本文介绍了Ruby on Rails 最佳实践 - 大控制器与小控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些关于 Ruby on Rails 中最佳实践的信息,特别是对于必须做很多事情的控制器,所以,一个简单的显示"操作现在是行.我知道,这不是很好,而且我有特定的代码.

I need some informations for the best practices in Ruby on Rails, especially with Controller who have to do a lot of things, so, a simple "show" action is now up to lines. I know, it's not really good, and I have specific code in it.

这是一个示例代码:

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

正如你所看到的,我在这里有很多逻辑,我必须检查转录是否结束,如果没有,请更新进度条(@sound.transcript_progress),如果是,我首先必须连接到一个soap 操作以获取XML 路径,然后通过FTP 获取XML,然后将其存储到Amazon S3(糟糕的SOAP,我必须重新解析所有响应......).

As you can see, I have a lot of logic here, I have to check if the transcription is over, if not, update the progress_bar (@sound.transcript_progress), if yes, i first have to connect to a soap action to get the XML path, then get the XML via FTP, then stock it to the Amazon S3 (Shitty SOAP, i have to reparse all response...).

在我所有的动作控制器中,我必须连接到 S3/SOAP/FTP,而不是以相同的顺序..所以我想为每个人做一堂课,就像在C++,一种抽象.我想要完成的东西,我不在乎(很多)如何完成.但是 MVC 的最佳实践是什么?我必须做一个新文件夹班级?"一个新的控制器?

In all my action controller, i have to connect on S3 / SOAP / FTP, not in the same order.. So i i'm thinking to do a class for each, like in C++, an abstraction. I want the stuff done, i don't care (a lot) how it's done. But what's the best practice with the MVC? I have to make a new folder "Class?" A new controller?

推荐答案

这更像是一个长篇评论,因为它解释了您的困境的根源,但没有提供解决方案.

This is more of a long-form comment, since it explains the origin of your dilemma, but provides no solutions.

问题其实是对 RoR 流行的 MVC 的误解造成的.

The problem actually is caused by misinterpretation of MVC, which RoR popularizes.

这是导致控制器内爆的两个因素的结合:

It is the combination of two factors, which are causing this implosion of controller:

  • 一方面,您有 贫血模型,因为,而不是真实模型层,RoR 使用 ORM 实例的集合.这样做的原因是 Rails 最初是作为快速原型设计(生成一次性代码)的框架而创建的.而原型制作正是 active record 最擅长的.使用脚手架,您可以轻松地从现有数据库生成活动记录结构.

  • On the one side you have anemic model, because, instead of real model layer, RoR uses collection of ORM instances. The reason for it is that Rails was originally created to be a framework for fast prototyping (generation of throw-away code). And prototyping is exactly what active record is best at. Using scaffolding, you can easily generate active record structures from existing databases.

但这会导致某些域业务逻辑在您的控制器中泄漏.

But this cause some of the domain business logic to leak in your controllers.

另一方面,您看到的是不存在的视图.由于目标是原型设计,Rails 倾向于通过将视图合并到控制器中来摆脱视图,这些视图实际上可以包含表示逻辑.现在缺失的视图被简单的模板取代,这些模板被称为视图".

On the other side you have the non-existent view. Since the goal was prototyping, Rails favored getting rid of views, which can actually contain presentation logic, by merging them into the controllers. The, now missing, views were replace with simple templates, which are just called "views".

这会强制控制器包含表示逻辑.

This forces controllers to contain presentation logic.

这两个因素就是为什么我很想断言 RoR 甚至不是 MVC 框架的原因.结果模式实际上更接近于 Model-View-Presenter.尽管它已被简化到开始打破关注点分离的程度.

These two factors would be the reason, why I am tempted to assert, that RoR is not even MVC framework. The resulting pattern is actually closer to Model-View-Presenter. Though it has been simplified to the point at which it starts to break Separation of Concerns.

这篇关于Ruby on Rails 最佳实践 - 大控制器与小控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆