我们如何避免控制器中方法的重复/重复 - 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+的主要内容,如果未能解决你的问题,请参考以下文章