Foundation: Create OptionsLike and BaseOptions
Phase: 1 - Foundation
Release Target: v2.x.0
Tracking Issue: #1647
RFC: docs/options-detach-plan.md
Overview
Create the foundational components for the new Options architecture:
Faraday::OptionsLike - Marker module for duck-typed interop
Faraday::BaseOptions - Abstract superclass with shared behavior
This establishes the base architecture that all Options subclasses will use.
Implementation Details
1. Create OptionsLike Module
File: lib/faraday/options_like.rb
# frozen_string_literal: true
module Faraday
# Marker module for Options-like objects.
# Enables duck-typed interop and integration with Utils.deep_merge!
module OptionsLike
end
end
Purpose: Allows both legacy Options and new BaseOptions classes to be treated uniformly in duck-typed contexts.
2. Create BaseOptions Class
File: lib/faraday/base_options.rb
# frozen_string_literal: true
module Faraday
# Abstract base class for Options-like classes.
# Provides common functionality for nested coercion, deep merging, and duplication.
class BaseOptions
include OptionsLike
# Subclasses must define:
# - MEMBERS: Array of attribute names (symbols)
# - COERCIONS: Hash mapping attribute names to coercion classes
class << self
# Create new instance from hash or existing instance
def from(value)
return value if value.is_a?(self)
return new if value.nil?
new(value)
end
end
def initialize(options = {})
options = options.to_hash if options.respond_to?(:to_hash)
self.class::MEMBERS.each do |key|
value = options[key] || options[key.to_s]
value = coerce(key, value)
instance_variable_set(:"@#{key}", value)
end
end
# Update this instance with values from another hash/instance
def update(obj)
obj = obj.to_hash if obj.respond_to?(:to_hash)
obj.each do |key, value|
key = key.to_sym
if self.class::MEMBERS.include?(key)
value = coerce(key, value)
instance_variable_set(:"@#{key}", value)
end
end
self
end
# Non-destructive merge
def merge(obj)
deep_dup.merge!(obj)
end
# Destructive merge (uses Utils.deep_merge!)
def merge!(obj)
obj = obj.to_hash if obj.respond_to?(:to_hash)
Utils.deep_merge!(to_hash, obj)
update(to_hash)
end
# Deep duplication
def deep_dup
self.class.new(
self.class::MEMBERS.each_with_object({}) do |key, hash|
value = instance_variable_get(:"@#{key}")
hash[key] = Utils.deep_dup(value)
end
)
end
# Convert to hash
def to_hash
self.class::MEMBERS.each_with_object({}) do |key, hash|
hash[key] = instance_variable_get(:"@#{key}")
end
end
# Inspect
def inspect
"#<#{self.class} #{to_hash.inspect}>"
end
private
def coerce(key, value)
coercion = self.class::COERCIONS[key]
return value unless coercion
return value if value.is_a?(coercion)
coercion.from(value)
end
end
end
3. Update Autoload
File: lib/faraday.rb
Add to autoloads section:
autoload :OptionsLike, 'faraday/options_like'
autoload :BaseOptions, 'faraday/base_options'
Tasks
Acceptance Criteria
Dependencies
Files to Create
lib/faraday/options_like.rb
lib/faraday/base_options.rb
spec/faraday/base_options_spec.rb
Files to Modify
lib/faraday.rb (add autoloads)
Backward Compatibility
No breaking changes - this only adds new classes, doesn't modify existing ones.
Foundation: Create OptionsLike and BaseOptions
Phase: 1 - Foundation
Release Target: v2.x.0
Tracking Issue: #1647
RFC: docs/options-detach-plan.md
Overview
Create the foundational components for the new Options architecture:
Faraday::OptionsLike- Marker module for duck-typed interopFaraday::BaseOptions- Abstract superclass with shared behaviorThis establishes the base architecture that all Options subclasses will use.
Implementation Details
1. Create OptionsLike Module
File:
lib/faraday/options_like.rbPurpose: Allows both legacy
Optionsand newBaseOptionsclasses to be treated uniformly in duck-typed contexts.2. Create BaseOptions Class
File:
lib/faraday/base_options.rb3. Update Autoload
File:
lib/faraday.rbAdd to autoloads section:
Tasks
lib/faraday/options_like.rblib/faraday/base_options.rbwith full implementationlib/faraday.rbspec/faraday/base_options_spec.rbwith comprehensive tests:.fromclass methodupdatemethodmerge(non-destructive)merge!(destructive)deep_dupto_hashinspectAcceptance Criteria
OptionsLikemodule exists and can be includedBaseOptionsprovides all shared functionalityDependencies
Files to Create
lib/faraday/options_like.rblib/faraday/base_options.rbspec/faraday/base_options_spec.rbFiles to Modify
lib/faraday.rb(add autoloads)Backward Compatibility
No breaking changes - this only adds new classes, doesn't modify existing ones.