Class: Steppe::Responder
- Inherits:
-
Plumb::Pipeline
- Object
- Plumb::Pipeline
- Steppe::Responder
- Defined in:
- lib/steppe/responder.rb
Overview
Handles response formatting for specific HTTP status codes and content types.
A Responder is a pipeline that processes a result and formats it into a Rack response. Each responder is registered for a specific range of status codes and content type, and includes a serializer to format the response body.
Constant Summary collapse
- DEFAULT_STATUSES =
(200..200).freeze
- DEFAULT_SERIALIZER =
Types::Static[{}.freeze].freeze
Instance Attribute Summary collapse
-
#accepts ⇒ ContentType
readonly
The content type pattern this responder matches (from Accept header).
-
#content_type ⇒ ContentType
readonly
The actual Content-Type header value set in the response.
-
#description ⇒ String?
Optional description of this responder (used in documentation).
-
#serializer ⇒ Serializer, Proc
readonly
The serializer used to format the response body.
-
#statuses ⇒ Range
readonly
The range of HTTP status codes this responder handles.
Class Method Summary collapse
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Compares two responders for equality.
-
#call(conn) ⇒ Result::Halt
Processes the result through the serializer pipeline and creates a Rack response.
-
#initialize(statuses: DEFAULT_STATUSES, accepts: ContentTypes::JSON, content_type: nil, serializer: nil) {|responder| ... } ⇒ Responder
constructor
Creates a new Responder instance.
-
#inspect ⇒ String
Human-readable representation of the responder.
-
#node_name ⇒ Symbol
Node name for pipeline inspection.
-
#serialize(serializer = nil) { ... } ⇒ void
Registers a serializer for this responder.
Constructor Details
#initialize(statuses: DEFAULT_STATUSES, accepts: ContentTypes::JSON, content_type: nil, serializer: nil) {|responder| ... } ⇒ Responder
Creates a new Responder instance.
89 90 91 92 93 94 95 96 97 98 |
# File 'lib/steppe/responder.rb', line 89 def initialize(statuses: DEFAULT_STATUSES, accepts: ContentTypes::JSON, content_type: nil, serializer: nil, &) @statuses = statuses.is_a?(Range) ? statuses : (statuses..statuses) @description = nil @accepts = ContentType.parse(accepts) @content_type = content_type ? ContentType.parse(content_type) : @accepts @content_type_subtype = @content_type.subtype.to_sym super(freeze_after: false, &) serialize(serializer) if serializer freeze end |
Instance Attribute Details
#accepts ⇒ ContentType (readonly)
Returns The content type pattern this responder matches (from Accept header).
59 60 61 |
# File 'lib/steppe/responder.rb', line 59 def accepts @accepts end |
#content_type ⇒ ContentType (readonly)
Returns The actual Content-Type header value set in the response.
62 63 64 |
# File 'lib/steppe/responder.rb', line 62 def content_type @content_type end |
#description ⇒ String?
Returns Optional description of this responder (used in documentation).
68 69 70 |
# File 'lib/steppe/responder.rb', line 68 def description @description end |
#serializer ⇒ Serializer, Proc (readonly)
Returns The serializer used to format the response body.
65 66 67 |
# File 'lib/steppe/responder.rb', line 65 def serializer @serializer end |
#statuses ⇒ Range (readonly)
Returns The range of HTTP status codes this responder handles.
56 57 58 |
# File 'lib/steppe/responder.rb', line 56 def statuses @statuses end |
Class Method Details
.inline_serializers ⇒ Object
43 44 45 |
# File 'lib/steppe/responder.rb', line 43 def self.inline_serializers @inline_serializers ||= {} end |
Instance Method Details
#==(other) ⇒ Boolean
Compares two responders for equality.
Two responders are equal if they handle the same status codes and content type.
143 144 145 |
# File 'lib/steppe/responder.rb', line 143 def ==(other) other.is_a?(Responder) && other.statuses == statuses && other.content_type == content_type end |
#call(conn) ⇒ Result::Halt
Processes the result through the serializer pipeline and creates a Rack response.
157 158 159 160 161 162 163 |
# File 'lib/steppe/responder.rb', line 157 def call(conn) conn = super(conn) conn.respond_with(conn.response.status) do |response| response[Rack::CONTENT_TYPE] = content_type.to_s Rack::Response.new(conn.value, response.status, response.headers) end end |
#inspect ⇒ String
Returns Human-readable representation of the responder.
148 |
# File 'lib/steppe/responder.rb', line 148 def inspect = "<#{self.class}##{object_id} #{description} statuses:#{statuses} content_type:#{content_type}>" |
#node_name ⇒ Symbol
Returns Node name for pipeline inspection.
151 |
# File 'lib/steppe/responder.rb', line 151 def node_name = :responder |
#serialize(serializer = nil) { ... } ⇒ void
This method returns an undefined value.
Registers a serializer for this responder.
The serializer is selected based on the content type’s subtype (:json or :html). For JSON responses, pass a Serializer class or a block that defines attributes. For HTML responses, pass a Papercraft template or block.
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/steppe/responder.rb', line 126 def serialize(serializer = nil, &block) raise ArgumentError, "this responder already has a serializer" if @serializer builder = self.class.inline_serializers.fetch(@content_type_subtype) @serializer = builder.call(serializer || block) step do |conn| output = @serializer.render(conn) conn.copy(value: output) end end |