Skip to content

Commit d63022f

Browse files
committed
🔧⚡️ Store Config attr_accessors in a Struct
Config values are stored in a struct rather than ivars to simplify: * ensuring that all config objects share a single object shape * querying only locally configured values, e.g for inspection.
1 parent 18fe6dd commit d63022f

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

lib/net/imap/config.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22
# :markup: markdown
33

4+
require_relative "config/attr_accessors"
5+
46
module Net
57
class IMAP
68

@@ -11,6 +13,7 @@ class IMAP
1113
# *NOTE:* Updates to config objects are not synchronized for thread-safety.
1214
#
1315
class Config
16+
include AttrAccessors
1417

1518
# The debug mode (boolean)
1619
attr_accessor :debug

lib/net/imap/config/attr_accessors.rb

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# frozen_string_literal: true
2+
3+
require "forwardable"
4+
5+
module Net
6+
class IMAP
7+
class Config
8+
9+
# Config values are stored in a struct rather than ivars to simplify:
10+
# * ensuring that all config objects share a single object shape
11+
# * querying only locally configured values, e.g for inspection.
12+
module AttrAccessors
13+
module Macros # :nodoc: internal API
14+
def attr_accessor(name) AttrAccessors.attr_accessor(name) end
15+
end
16+
private_constant :Macros
17+
18+
def self.included(mod)
19+
mod.extend Macros
20+
end
21+
private_class_method :included
22+
23+
extend Forwardable
24+
25+
def self.attr_accessor(name) # :nodoc: internal API
26+
name = name.to_sym
27+
def_delegators :data, name, :"#{name}="
28+
end
29+
30+
def self.attributes
31+
instance_methods.grep(/=\z/).map { _1.to_s.delete_suffix("=").to_sym }
32+
end
33+
private_class_method :attributes
34+
35+
def self.struct # :nodoc: internal API
36+
unless defined?(self::Struct)
37+
const_set :Struct, Struct.new(*attributes)
38+
end
39+
self::Struct
40+
end
41+
42+
def initialize # :notnew:
43+
super()
44+
@data = AttrAccessors.struct.new
45+
end
46+
47+
# Freezes the internal attributes struct, in addition to +self+.
48+
def freeze
49+
data.freeze
50+
super
51+
end
52+
53+
protected
54+
55+
attr_reader :data # :nodoc: internal API
56+
57+
private
58+
59+
def initialize_dup(other)
60+
super
61+
@data = other.data.dup
62+
end
63+
64+
end
65+
end
66+
end
67+
end

0 commit comments

Comments
 (0)