将控制器逻辑封装在导轨

时间:2017-06-06 21:04:32

标签: ruby-on-rails ruby model-view-controller

我有两个带有不同身份验证方案的控制器, 但他们几乎一样。

封装rails的最佳方法是什么? 另一个类或助手中的控制器的逻辑?

样品:

def ControllerA < BasicAuthController    
  def create
    blablacode
  end
end

def ControllerB < TokenAuthController
  def create
    blablacode
  end
end

这样做的正确方法是什么?用代码创建一个模型? 创建一个帮手?其他

4 个答案:

答案 0 :(得分:0)

我这样做:

#app/services/my_app/services/authentication.rb
class MyApp::Services::Authentication

  class < self

    def call(params={})
      new(params).call
    end

  end # Class Methods

  #==============================================================================================
  # Instance Methods
  #==============================================================================================

    def initialize(params)
      @params = params 
    end

    def call
      ... do a lot of clever stuff
      ... end by returning true or false
    end

  private

    def params() @params end

end

然后:

class FooController < ApplicationController
  before_action :authenticate

  def authenticate
    redirect_to 'some_path' unless MyApp::Services::Authenticate.call(with: 'some_params')
  end

end

答案 1 :(得分:0)

为什么不为单个控制器启用这两种方案?特别是如果唯一的区别是身份验证。您可以有两个app/controllers/concerns来封装两种身份验证方法,include Auth1include Auth2用于单个控制器,它只负责它管理的任何资源。

否则,服务是封装控制器逻辑的最佳方法。

services文件夹中创建一个名为app的文件夹,并在此处编写PORO课程。假设您的应用中有几个地方可以通过make Stripe支付费用。

# app/services/stripe_service.rb
module StripeService
  def customer(args)
    ...
  end

  def pay(amount, customer)
    ...
  end

  def reverse(stripe_txn_id)
    ...
  end
end
# controller
StripeService.customer(data)
=> <#Stripe::Customer>

或者如果你只需要做一件事。

# app/services/some_thing.rb
module SomeThing
  def call
    # do stuff
  end
end
# controller
SomeThing.call
=> # w/e

如果您需要具有多个reponsibilities的对象,则可以创建一个类。

class ReportingService
  def initialize(args)
    ...
  end

  def query
    ...
  end

  def data
    ...
  end

  def to_json
    ...
  end
end

https://blog.engineyard.com/2014/keeping-your-rails-controllers-dry-with-services

答案 2 :(得分:0)

最简单的方法是创建一个模块,然后将include放入其他控制器:

module ControllerMixin
  def create
    blablacode
  end
end

然而,剩下的问题是将此代码放在何处使其适用于Rails自动加载器,因为它需要在控制器之前加载。一种方法是将模块写入lib/目录中的文件,然后将其添加到自动加载路径(请参阅auto-loading-lib-files-in-rails-4

答案 3 :(得分:0)

简短回答,我选择创建一个帮助者

&#xA;&#xA;

来自答案中的所有建议

&#xA;&#xA;
    &#xA;
  • 创建一个模块:&#xA;看起来是正确的但是在 app 目录下面有逻辑并不合适。这不是一个外部模块或库,但&#xA;与我的应用程序的逻辑非常相关的东西。

  • &#xA;
  • 在一个控制器中集成不同的身份验证:&#xA;是一个很好的建议,但我必须改变我的所有逻辑应用程序。

  • &#xA;
  • 创建帮助:&#xA;在我看来,更好的解决方案,我有一个帮助程序的代码,和& #xA;在app目录中,非常接近其他逻辑。

  • &#XA;
&#XA;