簡體   English   中英

在另一個類中調用方法?

[英]Calling a method in another class?

我在不同的命名空間(a和b)中有兩個控制器,如下所示:

class A::TechnologiesController < ApplicationController
  def index
    render json: Technology.all
  end
end

class B::TechnologiesController < ApplicationController
  def index
    render json: Technology.all
  end
end

這兩個動作執行相同的邏輯,我相信這是重復。 我想消除重復,因此如何在下面的命名空間中借用代碼?

class B::TechnologiesController < ApplicationController
  def index
    A::TechnologiesController.method(:index).call self
  end
end

回答注釋中的一個隱式問題: 如果且只有該方法所屬類的調用bind is_a?()實例的對象, 則可以使用UnboundMethod#bind借用該方法:

def index
  A::TechnologiesController.instance_method(:index).bind(self).()
end

但這既不是慣用法也不是可讀的。 一個人應該使用mixin:

module Mixins::TechnologiesController
  def index
    render json: Technology.all
  end
end

class A::TechnologiesController < ApplicationController
  include Mixins::TechnologiesController
end
class B::TechnologiesController < ApplicationController
  include Mixins::TechnologiesController
end

或共同祖先:

class Base::TechnologiesController < ApplicationController
  def index
    render json: Technology.all
  end
end
class A::TechnologiesController < Base::TechnologiesController; end
class B::TechnologiesController < Base::TechnologiesController; end

獎勵軌道:在Rails中,可以使用Module#delegate monkeypatch。


獎金軌道2:存儲為常量的proc的實現:

class A::TechnologiesController < ApplicationController
  INDEX = -> { render json: Technology.all }
  def index
    INDEX.()
  end
end

class B::TechnologiesController < ApplicationController
  def index
    A::INDEX.()
  end
end

這是mixin的一個很好的例子。
有了它,您可以干燥您的代碼,而不必調用另一個控制器的方法。

這是模塊:

module CommonInterface
  def render_technology
    render :json, Technology.all
  end
end

這將是您的控制器

class B::TechnologiesController < ApplicationController
  include CommonInterface
  def index
    render_technology
  end
end

如果您確實想弄干東西,那么祖先和mixin答案確實很好,但是我認為您不一定必須這么做。 render json:位屬於控制器動作。 您希望您的操作能夠在兩個控制器中呈現某些內容。

查詢是一些可能以同樣的方式隨着時間的推移我想改變Technology.all ,所以你可以抽象的某個地方,但同樣,這可能是一個好主意,以觀望為主,如果是這樣的話。

如果確實使用mixins或基類,則可以將兩個控制器耦合在一起,這可能很好。 但同樣,您可能只想稍后再做出此決定。

您可以通過在ApplicationController中創建一個super方法來解決上述問題,並且需要在每個控制器中添加一個以上方法,以將值傳遞給不僅可以用於Technology模型的super方法,還可以將其用於任何其他模型。

舉個例子

在應用程序控制器中

    class ApplicationController < ActionController::Base
      def index
        @collection = model
      end
    end

在每個控制器中,我們可以像這樣調用上面的方法

    class StudentsController < ApplicationController

      def index
        super
      end

      def model
        Student
      end
    end




    class JobsController < ApplicationController
      def index
        super
      end
      def model
        Job
      end
    end

您將在@collection中獲取的數據可以在視圖中使用,例如

對於app / views / students / index.html.erb

    <% @collection.all.each do |student| %>
      <tr>
        <td><%= student.Name %></td>
        <td><%= student.Email %></td>
      </tr>
    <% end %>

對於app / views / jobs / index.html.erb

    <% @collection.all.each do |job| %>
      <tr>
        <td><%= job.id %></td>
        <td><%= job.exp %></td>
      </tr>
    <% end %>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM