我们如何避免控制器中 duplication/repeatition 的方法 - RAILS 3+

How can we avoid duplication/repeatition of methods in controllers - RAILS 3+

我正在使用 rails.One 上的 ruby 构建示例电子商务应用程序,我的控制器名称是 "products_controller"。此控制器也作为嵌套 controller.The 这些控制器内的动作是 same.How 我们可以在不重复代码的情况下表示这些动作吗? 代码示例如下。

app/controllers/products_controller.rb

def index
@product = Product.all
@vari = @products.variants
.............
.............
end

app/controllers/master_admins/products_controller.rb

def index
@product = Product.all
@vari = @products.variants
.............
.............
end

app/controllers/master_admins/properties_controller.rb

def product
@product = Product.all
@vari = @products.variants
.............
.............
end

上面的动作包含相同的一组codes.How我们能否重构它以使代码不再重复。

提前致谢....

您可以这样做:

class GenericController < ActiveRecord::Base
  def index
    do something interesting
  end
end

class PropertiesController < GenericController
  # index is done
end

class ProductsController < GenericController
  # index is done
end

我建议使用 concerns,它非常适合 DRY。

对于controller,常用的方法可以放这里:

在我的app/controllers/concerns/common.rb

module Common
  extend ActiveSupport::Concern

  module ClassMethods
    ## This is a Class method, call it just like you call any other class method
    def get_products_and_variants
      @product = Self.all
      @vari = @product.variants
    end
  end

## Instance method, if you don't want aclass method, use this instance method
def my_instance_method
  ## code for method
end

然后在controller中包含common.rb调用*

include Common

def index
  ## This will make @product and @vari available
  Product.get_products_and_variants

  # ............
end



## Other method using same method call
def product
  ## This will make @product and @vari available
  Product.get_products_and_variants

  # .............
end

如果您有多个 class 使用此 class 方法,您可以使用类似这样的方法(在 common.rb 中):

def get_details        
  if self == Product
     ## Get products
  elsif self == Variant
     ## Get variants
  elsif self == ProductDetail
     ## Get product details
  end              
end

您可以在控制器中使用before_action。它会在执行 find_product 之前执行 index:

before_action :find_product, only: :index

def find_product
    @product = Product.all
    @vari = @products.variants      
end

def index
# some useful code
end

你可以把"only:"部分去掉,在其他动作之前执行find_product,或者移到A​​pplicationController(或其他父控制器class)在所有对应的控制器中执行before_action