Ruby'返回'另一种方法的方法?

时间:2015-11-11 09:52:31

标签: ruby-on-rails ruby refactoring

由于某些历史原因,在Rails项目中,TigerElephant中的一段代码是相同的。

我不喜欢重复,但如果我在AnimalController课程中创建新方法并将这些代码移入其中,我就无法return walk新方法中的{}或running方法。

我认为从另一种方法返回可能不是一个好习惯,但我真的很讨厌重复,有人可以帮我重构吗?

class AnimalController
  # I want create a new method here
  #def all_in
  #end
end

class TigerController < AnimalController
  def running  # This is an Action
    some_different_codes...

    if arm.blank?
      render_not_found
      return      # <- how can I return `running` from the new method?
    end
    if lag.nil?
      invalid_id
      return      # <- 
    end

    some_different_codes...
  end
end

class ElephantController < AnimalController
  def walk     # This is an Action
    some_different_codes...

    if arm.blank?
      render_not_found
      return
    end
    if lag.nil?
      invalid_id
      return
    end

    some_different_codes...
  end
end

2 个答案:

答案 0 :(得分:2)

如果不希望,方法无法使其调用者返回。所以这个新方法将执行检查(在渲染时),它将返回检查结果。调用方法分析返回值并决定要执行的操作。这些方面的东西:

class AnimalController
  def all_in
    if invalid_id
      render_not_found
      return false
    end

    if lag.nil?
      invalid_id
      return false
    end

    true
  end
end

class TigerController < AnimalController
  def running  # This is an Action
    some_different_codes...

    return unless all_in

    some_different_codes...
  end
end

答案 1 :(得分:0)

可以好好查看callbackssuperclassing

回调基本上允许您根据其他功能的响应在代码中运行登录。

因为我们将它们全部放在Rails上,所以没有多少人真正欣赏他们所做的事情。如果您曾经在JS中实现它们,那么您将了解它们的全部内容!

-

超级类别是您从现有类继承的地方 - 允许您使用(和扩展)该类具有的功能。这是 super 命令的来源。

我这样做(实际上看起来像Sergio的答案,这是令人放心的):

#app/controllers/animals_controller.rb
class AnimalsController < ApplicationController

   private 

   def all_in?
       if invalid_id
          return false
       end
       if lag.nil?
          invalid_id
          return false
       end
       true #-> ruby automatically returns the last line 
   end
end

以上是您调用回调的内容 - 您可以调用all_in(在实例中)并收到{{1} } responsetrue

这将使您能够调用该方法(如果您false,该方法将在链中可用:

superclassing

现在,您必须注意一些事情。

此类行为应放在您应用的控制器中 - 它应该在您的模型中

#app/controllers/elephants_controller.rb
class ElephantController < AnimalController
  def walk     # This is an Action
    some_different_codes...

    if all_in?
       some_different_codes...
    end
  end
end

以上称为STI (Single Table Inheritance)。它基本上是一种使用其他&#34;依赖&#34;对主模型进行子类化的方法。模特儿他们的方法。

因为ruby是object orientated,所以你应该在对象本身上调用特定于对象的方法;

#app/models/animal.rb
class Animal < ActiveRecord::Base
   def walk
   end
end

#app/models/animals/elephant.rb
class Elephant < Animal
   def walk
      super ...
   end
end

#app/models/animals/tiger.rb
class Tiger < Animal
end

这或多或少是state machine

的缩影
#config/routes.rb
resources :tigers, :elephants, controller: :animals

#url.com/tigers/
#url.com/elephants/

#app/controllers/animals_controller.rb
class AnimalsController < ApplicationController
   def show
     @tiger = Tiger.find params[:id]
     @tiger.walk
   end
end