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

Posted

技术标签:

【中文标题】我们如何避免控制器中方法的重复/重复 - RAILS 3+【英文标题】:How can we avoid duplication/repeatition of methods in controllers - RAILS 3+ 【发布时间】:2015-06-04 22:39:13 【问题描述】:

我正在使用 ruby​​ on rails 构建一个示例电子商务应用程序。我的控制器名称之一是“products_controller”。该控制器也作为嵌套控制器放置在内部。这些控制器内部的操作是相同的。我们如何表示这些动作无需重复代码。 代码示例如下。

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

上述动作包含相同的代码集。我们如何重构它以使代码不会重复。

提前谢谢....

【问题讨论】:

我认为更好的问题是为什么需要多个具有相同代码的控制器?如果您担心访问控制,为什么不使用角色来处理呢? 我也在嵌套控制器中使用这组代码。这个产品控制器索引操作发生在我项目的以下 url 中。 "localhost:3000/products","localhost:3000/master_admins/products","localhost:3000/property_admins/products"。 【参考方案1】:

我建议使用concerns,这对于 DRY 来说非常棒。

对于控制器,常用的方法可以放在这里:

在我的 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

然后,通过在控制器中包含 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

如果你有多个类使用这个类方法,你可以使用这样的东西(在common.rb):

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

【讨论】:

我能用这样的东西吗..... product = Product.all product_category = ProductCategory.all product_sub_category = ProductSubCategory.all properties = product_sub_category.properties 是的@Manikandan,对于在common.rb中使用相同类方法的多个类,我建议使用if elseif编码方式(如方法get_details),以便您可以检查哪个类正在调用例如 self==Product 并且可以继续。您也可以使用包含 :) 预加载 :) 感谢@Milind 的帮助......这帮助我解决了我的问题......再次感谢您在这方面花费宝贵的时间......:)【参考方案2】:

你可以这样做:

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

【讨论】:

【参考方案3】:

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

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,或将其移动到 ApplicationController(或其他父控制器class) 在所有对应的控制器中执行before_action

【讨论】:

以上是关于我们如何避免控制器中方法的重复/重复 - RAILS 3+的主要内容,如果未能解决你的问题,请参考以下文章

避免重复造轮子

如何避免 writeToBq 步骤中数据流束管道中的重复?

kafka防止消息重复消费

如何以编程方式创建展开转场[重复]

如何避免重复验证事件 Winforms

如何避免 redux 中的重复代码(鸭子方法)?