Rails Presenter - 与 2 个具有相同属性的不同模型交互
Rails Presenter - Interacting with 2 different models that share the same attribute
我在大型 Rails 应用程序中有 2 个模型 room
和 inquiry
。他们都有一个 attribute/column cancellation_policy
.
在进行查询(别名:预订)时,cancellation_policy
从 room.cancellation_policy
复制到 inquiry.cancellation_policy
。
我目前有一个 RoomPresenter
,它使用 room
对象初始化,如下所示:
def initialize(room, current_user = nil)
@room = room
@current_user = current_user
end
这位主持人对 'present' 和 room
做了很多事情。然而,我最近添加了一堆方法,例如:
def cancellation_policy_type
def get_cancellation_policy_text_with_formatting
etc.
在各种 RoomController(跨越不同的命名空间)中,我可以用 @room_presenter = RoomPresenter.new(@room)
实例化并在相关视图中调用方法,例如 @room_presenter. def cancellation_policy_type
。
我觉得可以采取以下做法
class RoomPresenter
# gives me access to RoomPresenter#cancellation_policy (see below)
include RoomPresenters::CancellationPolicy
def initialize(room)
@room = room
end
end
# app/presenters/room_presenters/cancellation_policy.rb
module RoomPresenters
module CancellationPolicy
def cancellation_policy
###
end
end
end
这将以合乎逻辑的方式将 room
presenter 方法与 room.cancellation_policy
分开,但这并不能解决 Room
和 Inquiry
之间的问题以及一个愿望不要混淆这两个不同的 类.
然而,我的主要 question/cluelessness 出现在将其纳入查询模型和房间模型时。以下对我来说似乎都是错误的:
class InquiryPresenter (would be initialized with an inquiry).
include RoomPresenters::CancellationPolicy
同样:
class InquiryPresenter
#lots of duplicated code doing the same thing/same methods.
我试图了解如何最好地组织这种类型的逻辑,但不确定最佳方法。
底层输出非常简单 - 每个方法都只是输出一些纯文本或 html,但随着应用程序的进一步发展,我发现需要确保 Presenters
遵守 SRP .
如果需要进一步解释和示例,请告诉我。
我会首先为您的演示者创建一个基础 class 以减少重复的数量
class BasePresenter < Delegator
def initialize(object)
@object = object
end
# required by Delegator
def __getobj__
@object
end
def self.model_name
self.name.chomp("Presenter")
end
def self.model_key
self.model_name.underscore.to_sym
end
alias_method :__getobj__, :object
# declares a getter based on the class name
# UserPresenter -> #user
alias_method :__getobj__, self.model_key
end
使用 stdlib Delegator
作为基础 class 意味着它将缺少的方法委托给包装的 object.
例如:
RoomPresenter.new(@room).id == @room.id
我们还创建了一个通用初始化程序,并使用 @object
作为内部存储。可以通过 #object
或从 class 名称派生的自定义 getter 访问内部存储的 object。
这会让您减少演示者的样板文件数量。
class RoomPresenter < BasePresenter
include RoomPresenters::CancellationPolicy
end
class InquiryPresenter < BasePresenter
include RoomPresenters::CancellationPolicy
end
您还可以为您的模型创建一个 mixin,让您可以 @room.present
而不是 RoomPresenter.new(@room)
。
它还可以让您通过 @rooms.map(&:present)
.
获得礼物 collection
module Presentable
def present
"#{self.class.name}Presenter".constantize.new(self)
end
end
我在大型 Rails 应用程序中有 2 个模型 room
和 inquiry
。他们都有一个 attribute/column cancellation_policy
.
在进行查询(别名:预订)时,cancellation_policy
从 room.cancellation_policy
复制到 inquiry.cancellation_policy
。
我目前有一个 RoomPresenter
,它使用 room
对象初始化,如下所示:
def initialize(room, current_user = nil)
@room = room
@current_user = current_user
end
这位主持人对 'present' 和 room
做了很多事情。然而,我最近添加了一堆方法,例如:
def cancellation_policy_type
def get_cancellation_policy_text_with_formatting
etc.
在各种 RoomController(跨越不同的命名空间)中,我可以用 @room_presenter = RoomPresenter.new(@room)
实例化并在相关视图中调用方法,例如 @room_presenter. def cancellation_policy_type
。
我觉得可以采取以下做法
class RoomPresenter
# gives me access to RoomPresenter#cancellation_policy (see below)
include RoomPresenters::CancellationPolicy
def initialize(room)
@room = room
end
end
# app/presenters/room_presenters/cancellation_policy.rb
module RoomPresenters
module CancellationPolicy
def cancellation_policy
###
end
end
end
这将以合乎逻辑的方式将 room
presenter 方法与 room.cancellation_policy
分开,但这并不能解决 Room
和 Inquiry
之间的问题以及一个愿望不要混淆这两个不同的 类.
然而,我的主要 question/cluelessness 出现在将其纳入查询模型和房间模型时。以下对我来说似乎都是错误的:
class InquiryPresenter (would be initialized with an inquiry).
include RoomPresenters::CancellationPolicy
同样:
class InquiryPresenter
#lots of duplicated code doing the same thing/same methods.
我试图了解如何最好地组织这种类型的逻辑,但不确定最佳方法。
底层输出非常简单 - 每个方法都只是输出一些纯文本或 html,但随着应用程序的进一步发展,我发现需要确保 Presenters
遵守 SRP .
如果需要进一步解释和示例,请告诉我。
我会首先为您的演示者创建一个基础 class 以减少重复的数量
class BasePresenter < Delegator
def initialize(object)
@object = object
end
# required by Delegator
def __getobj__
@object
end
def self.model_name
self.name.chomp("Presenter")
end
def self.model_key
self.model_name.underscore.to_sym
end
alias_method :__getobj__, :object
# declares a getter based on the class name
# UserPresenter -> #user
alias_method :__getobj__, self.model_key
end
使用 stdlib Delegator
作为基础 class 意味着它将缺少的方法委托给包装的 object.
例如:
RoomPresenter.new(@room).id == @room.id
我们还创建了一个通用初始化程序,并使用 @object
作为内部存储。可以通过 #object
或从 class 名称派生的自定义 getter 访问内部存储的 object。
这会让您减少演示者的样板文件数量。
class RoomPresenter < BasePresenter
include RoomPresenters::CancellationPolicy
end
class InquiryPresenter < BasePresenter
include RoomPresenters::CancellationPolicy
end
您还可以为您的模型创建一个 mixin,让您可以 @room.present
而不是 RoomPresenter.new(@room)
。
它还可以让您通过 @rooms.map(&:present)
.
module Presentable
def present
"#{self.class.name}Presenter".constantize.new(self)
end
end