Ruby 'return' 一个方法来自另一个方法?

Ruby 'return' a method from another method?

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

我不喜欢重复,但如果我在 AnimalController class 中创建一个新方法并将这些代码移入其中,我就无法 return [=来自新方法的 17=] 或 running 方法。

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

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

一个方法不能让其调用者 return,如果它不想的话。所以这个新方法将执行检查(同时渲染一些东西)并且它将 return 检查结果。调用方方法分析 return 值并决定要做什么。沿着这些线的东西:

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

可能是查找有关 callbacks and superclassing:

的好机会

回调 基本上允许您运行 根据另一个函数的响应在代码中登录。

由于我们到处都有他们 Rails,所以真正欣赏他们所做的事情的人并不多。如果你曾经用 JS 实现过它们,你就会了解它们!

-

Superclassing 是您从现有 class 继承的地方 - 允许您使用(和扩展)[=70= 的功能] 已。这就是 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(在一个实例中)并收到 response truefalse

这将使您能够调用该方法(如果您是 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

现在,有件事你必须知道。

这种类型的行为应该放在您应用的控制器中——它应该放在您的中型号:

#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

以上称为STI (Single Table Inheritance)。它基本上是一种使用其他 "dependent" 模型及其方法对主模型进行子class 的方法。

由于 ruby 是 object orientated,您应该在对象本身上调用特定于对象的方法;

#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

这或多或少体现在 state machine:

class Vehicle
  attr_accessor :seatbelt_on, :time_used, :auto_shop_busy

  state_machine :state, :initial => :parked do
    before_transition :parked => any - :parked, :do => :put_on_seatbelt

    after_transition :on => :crash, :do => :tow
    after_transition :on => :repair, :do => :fix
    after_transition any => :parked do |vehicle, transition|
      vehicle.seatbelt_on = false
    end

...