我们如何避免控制器中 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,或者移到ApplicationController(或其他父控制器class)在所有对应的控制器中执行before_action。
我正在使用 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,或者移到ApplicationController(或其他父控制器class)在所有对应的控制器中执行before_action。