I have 2 models in a large Rails app room and inquiry. They both share an attribute/column cancellation_policy.
At the point at the point at which an inquiry (alias: booking) is made the cancellation_policy is copied from the room.cancellation_policy to inquiry.cancellation_policy.
I currently have a RoomPresenter that is initialized with a room object like this:
def initialize(room, current_user = nil)
@room = room
@current_user = current_user
end
This presenter does various things to 'present' a room. I recently however added a bunch of methods such as:
def cancellation_policy_type
def get_cancellation_policy_text_with_formatting
etc.
In various RoomControllers (across different namespaces) I can then instantiate with @room_presenter = RoomPresenter.new(@room) and call methods in the relevant views as expected with @room_presenter. def cancellation_policy_type for example.
I feel that I can take the following approach
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
Which would separate out the room presenter methods from the room.cancellation_policy in a logical way but this doesn't solve issue between Room and Inquiry and a desire to not confused the two different classes.
However my main question/cluelessness comes when it comes to incorporating this across both the inquiry model and the room model. The following all seem very wrong to me:
class InquiryPresenter (would be initialized with an inquiry).
include RoomPresenters::CancellationPolicy
as equally:
class InquiryPresenter
#lots of duplicated code doing the same thing/same methods.
I am trying to understand how best to organise this type of logic, but am not sure of the best approach.
The underlying output is extremely simple - each method is just outputting some plain text or html, but as the app grows further I see the need to make sure the Presenters adhere to the SRP.
Please let me know if further explanation, examples are needed.
I would start by creating a base class for your presenters to reduce the amount of duplication
Using the stdlib
Delegatoras the base class means it will delegate missing methods to the wrapped object.For example:
We also create a generic initializer and use
@objectfor the internal storage. The internally stored object can be accessed by#objector a custom getter derived from the class name.This will let you wheedle down on the amount of boilerplate in your presenters.
You can also create a mixin for your models that lets you do
@room.presentinstead ofRoomPresenter.new(@room).It would also let you get a presented collection by doing
@rooms.map(&:present).