servus 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/settings.json +9 -0
- data/CHANGELOG.md +45 -1
- data/READme.md +120 -15
- data/docs/features/6_guards.md +356 -0
- data/docs/features/guards_naming_convention.md +540 -0
- data/docs/integration/1_configuration.md +52 -2
- data/lib/generators/servus/guard/guard_generator.rb +75 -0
- data/lib/generators/servus/guard/templates/guard.rb.erb +69 -0
- data/lib/generators/servus/guard/templates/guard_spec.rb.erb +65 -0
- data/lib/servus/base.rb +9 -1
- data/lib/servus/config.rb +17 -2
- data/lib/servus/events/emitter.rb +3 -3
- data/lib/servus/guard.rb +289 -0
- data/lib/servus/guards/falsey_guard.rb +59 -0
- data/lib/servus/guards/presence_guard.rb +80 -0
- data/lib/servus/guards/state_guard.rb +62 -0
- data/lib/servus/guards/truthy_guard.rb +61 -0
- data/lib/servus/guards.rb +48 -0
- data/lib/servus/helpers/controller_helpers.rb +20 -48
- data/lib/servus/railtie.rb +11 -3
- data/lib/servus/support/errors.rb +69 -140
- data/lib/servus/support/message_resolver.rb +166 -0
- data/lib/servus/version.rb +1 -1
- data/lib/servus.rb +5 -0
- metadata +13 -8
- data/builds/servus-0.0.1.gem +0 -0
- data/builds/servus-0.1.1.gem +0 -0
- data/builds/servus-0.1.2.gem +0 -0
- data/builds/servus-0.1.3.gem +0 -0
- data/builds/servus-0.1.4.gem +0 -0
- data/builds/servus-0.1.5.gem +0 -0
- data/docs/current_focus.md +0 -569
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Servus
|
|
4
|
+
module Support
|
|
5
|
+
# Resolves message templates with interpolation support.
|
|
6
|
+
#
|
|
7
|
+
# Handles multiple template formats:
|
|
8
|
+
# - String: Static or with %{key} / %<key>s interpolation
|
|
9
|
+
# - Symbol: I18n key lookup with fallback
|
|
10
|
+
# - Hash: Inline translations keyed by locale
|
|
11
|
+
# - Proc: Dynamic template evaluated at runtime
|
|
12
|
+
#
|
|
13
|
+
# @example Basic string interpolation
|
|
14
|
+
# resolver = MessageResolver.new(
|
|
15
|
+
# template: 'Hello, %<name>s!',
|
|
16
|
+
# data: { name: 'World' }
|
|
17
|
+
# )
|
|
18
|
+
# resolver.resolve # => "Hello, World!"
|
|
19
|
+
#
|
|
20
|
+
# @example With I18n symbol
|
|
21
|
+
# resolver = MessageResolver.new(template: :greeting)
|
|
22
|
+
# resolver.resolve # => I18n.t('greeting') or "Greeting" fallback
|
|
23
|
+
#
|
|
24
|
+
# @example With inline translations
|
|
25
|
+
# resolver = MessageResolver.new(
|
|
26
|
+
# template: { en: 'Hello', es: 'Hola' }
|
|
27
|
+
# )
|
|
28
|
+
# resolver.resolve # => "Hello" (or "Hola" if I18n.locale == :es)
|
|
29
|
+
#
|
|
30
|
+
# @example With proc and context
|
|
31
|
+
# resolver = MessageResolver.new(
|
|
32
|
+
# template: -> { "Balance: #{balance}" }
|
|
33
|
+
# )
|
|
34
|
+
# resolver.resolve(context: account) # => "Balance: 100"
|
|
35
|
+
#
|
|
36
|
+
class MessageResolver
|
|
37
|
+
# @return [String, Symbol, Hash, Proc, nil] the message template
|
|
38
|
+
attr_reader :template
|
|
39
|
+
|
|
40
|
+
# @return [Hash, Proc, nil] the interpolation data or data-providing block
|
|
41
|
+
attr_reader :data
|
|
42
|
+
|
|
43
|
+
# @return [String, nil] the I18n scope prefix for symbol templates
|
|
44
|
+
attr_reader :i18n_scope
|
|
45
|
+
|
|
46
|
+
# Creates a new message resolver.
|
|
47
|
+
#
|
|
48
|
+
# @param template [String, Symbol, Hash, Proc, nil] the message template
|
|
49
|
+
# @param data [Hash, Proc, nil] interpolation data or block returning data
|
|
50
|
+
# @param i18n_scope [String] prefix for I18n lookups (default: nil)
|
|
51
|
+
def initialize(template:, data: nil, i18n_scope: nil)
|
|
52
|
+
@template = template
|
|
53
|
+
@data = data
|
|
54
|
+
@i18n_scope = i18n_scope
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Resolves the template to a final string.
|
|
58
|
+
#
|
|
59
|
+
# @param context [Object, nil] object for evaluating Proc templates/data blocks
|
|
60
|
+
# @return [String] the resolved and interpolated message
|
|
61
|
+
def resolve(context: nil)
|
|
62
|
+
resolved_template = resolve_template(context)
|
|
63
|
+
resolved_data = resolve_data(context)
|
|
64
|
+
|
|
65
|
+
interpolate(resolved_template, resolved_data)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Resolves the template to a string based on its type.
|
|
71
|
+
#
|
|
72
|
+
# @param context [Object, nil] evaluation context for Proc templates
|
|
73
|
+
# @return [String] the resolved template string
|
|
74
|
+
def resolve_template(context)
|
|
75
|
+
case template
|
|
76
|
+
when Symbol then resolve_i18n_template
|
|
77
|
+
when Proc then resolve_proc_template(context)
|
|
78
|
+
when Hash then resolve_locale_template
|
|
79
|
+
else template.to_s
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Resolves I18n symbol template with fallback.
|
|
84
|
+
#
|
|
85
|
+
# @return [String] the translated string or humanized fallback
|
|
86
|
+
def resolve_i18n_template
|
|
87
|
+
key = build_i18n_key
|
|
88
|
+
fallback = humanize_symbol(template)
|
|
89
|
+
|
|
90
|
+
if defined?(I18n)
|
|
91
|
+
I18n.t(key, default: fallback)
|
|
92
|
+
else
|
|
93
|
+
fallback
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Builds the full I18n key from template and scope.
|
|
98
|
+
#
|
|
99
|
+
# @return [String, Symbol] the I18n lookup key
|
|
100
|
+
def build_i18n_key
|
|
101
|
+
return template if template.to_s.include?('.')
|
|
102
|
+
return template unless i18n_scope
|
|
103
|
+
|
|
104
|
+
"#{i18n_scope}.#{template}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Converts a symbol to a human-readable string.
|
|
108
|
+
#
|
|
109
|
+
# @param sym [Symbol] the symbol to humanize
|
|
110
|
+
# @return [String] humanized string
|
|
111
|
+
def humanize_symbol(sym)
|
|
112
|
+
sym.to_s.tr('_', ' ').capitalize
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Evaluates a Proc template in the given context.
|
|
116
|
+
#
|
|
117
|
+
# @param context [Object, nil] the evaluation context
|
|
118
|
+
# @return [String] the proc result as string
|
|
119
|
+
def resolve_proc_template(context)
|
|
120
|
+
result = context ? context.instance_exec(&template) : template.call
|
|
121
|
+
result.to_s
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Resolves a Hash template by current locale.
|
|
125
|
+
#
|
|
126
|
+
# @return [String] the localized string
|
|
127
|
+
def resolve_locale_template
|
|
128
|
+
locale = current_locale
|
|
129
|
+
(template[locale] || template[:en] || template.values.first).to_s
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Returns the current I18n locale or :en.
|
|
133
|
+
#
|
|
134
|
+
# @return [Symbol] the current locale
|
|
135
|
+
def current_locale
|
|
136
|
+
defined?(I18n) ? I18n.locale : :en
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Resolves data to a Hash for interpolation.
|
|
140
|
+
#
|
|
141
|
+
# @param context [Object, nil] evaluation context for Proc data
|
|
142
|
+
# @return [Hash] the interpolation data
|
|
143
|
+
def resolve_data(context)
|
|
144
|
+
case data
|
|
145
|
+
when Proc then context ? context.instance_exec(&data) : data.call
|
|
146
|
+
when Hash then data
|
|
147
|
+
else {}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Interpolates data into the template string.
|
|
152
|
+
#
|
|
153
|
+
# @param template_str [String] the template with placeholders
|
|
154
|
+
# @param data_hash [Hash] the interpolation data
|
|
155
|
+
# @return [String] the interpolated string
|
|
156
|
+
def interpolate(template_str, data_hash)
|
|
157
|
+
return template_str if data_hash.empty?
|
|
158
|
+
|
|
159
|
+
template_str % data_hash
|
|
160
|
+
rescue KeyError, ArgumentError => e
|
|
161
|
+
warn "MessageResolver interpolation failed: #{e.message}"
|
|
162
|
+
template_str
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
data/lib/servus/version.rb
CHANGED
data/lib/servus.rb
CHANGED
|
@@ -24,6 +24,7 @@ require_relative 'servus/support/response'
|
|
|
24
24
|
require_relative 'servus/support/validator'
|
|
25
25
|
require_relative 'servus/support/errors'
|
|
26
26
|
require_relative 'servus/support/rescuer'
|
|
27
|
+
require_relative 'servus/support/message_resolver'
|
|
27
28
|
|
|
28
29
|
# Events
|
|
29
30
|
require_relative 'servus/events/errors'
|
|
@@ -31,6 +32,10 @@ require_relative 'servus/events/bus'
|
|
|
31
32
|
require_relative 'servus/events/emitter'
|
|
32
33
|
require_relative 'servus/event_handler'
|
|
33
34
|
|
|
35
|
+
# Guards (guards.rb loads defaults based on config)
|
|
36
|
+
require_relative 'servus/guard'
|
|
37
|
+
require_relative 'servus/guards'
|
|
38
|
+
|
|
34
39
|
# Core
|
|
35
40
|
require_relative 'servus/version'
|
|
36
41
|
require_relative 'servus/base'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: servus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sebastian Scholl
|
|
@@ -88,21 +88,16 @@ files:
|
|
|
88
88
|
- LICENSE.txt
|
|
89
89
|
- READme.md
|
|
90
90
|
- Rakefile
|
|
91
|
-
- builds/servus-0.0.1.gem
|
|
92
|
-
- builds/servus-0.1.1.gem
|
|
93
|
-
- builds/servus-0.1.2.gem
|
|
94
|
-
- builds/servus-0.1.3.gem
|
|
95
|
-
- builds/servus-0.1.4.gem
|
|
96
|
-
- builds/servus-0.1.5.gem
|
|
97
91
|
- docs/core/1_overview.md
|
|
98
92
|
- docs/core/2_architecture.md
|
|
99
93
|
- docs/core/3_service_objects.md
|
|
100
|
-
- docs/current_focus.md
|
|
101
94
|
- docs/features/1_schema_validation.md
|
|
102
95
|
- docs/features/2_error_handling.md
|
|
103
96
|
- docs/features/3_async_execution.md
|
|
104
97
|
- docs/features/4_logging.md
|
|
105
98
|
- docs/features/5_event_bus.md
|
|
99
|
+
- docs/features/6_guards.md
|
|
100
|
+
- docs/features/guards_naming_convention.md
|
|
106
101
|
- docs/guides/1_common_patterns.md
|
|
107
102
|
- docs/guides/2_migration_guide.md
|
|
108
103
|
- docs/integration/1_configuration.md
|
|
@@ -189,6 +184,9 @@ files:
|
|
|
189
184
|
- lib/generators/servus/event_handler/event_handler_generator.rb
|
|
190
185
|
- lib/generators/servus/event_handler/templates/handler.rb.erb
|
|
191
186
|
- lib/generators/servus/event_handler/templates/handler_spec.rb.erb
|
|
187
|
+
- lib/generators/servus/guard/guard_generator.rb
|
|
188
|
+
- lib/generators/servus/guard/templates/guard.rb.erb
|
|
189
|
+
- lib/generators/servus/guard/templates/guard_spec.rb.erb
|
|
192
190
|
- lib/generators/servus/service/service_generator.rb
|
|
193
191
|
- lib/generators/servus/service/templates/arguments.json.erb
|
|
194
192
|
- lib/generators/servus/service/templates/result.json.erb
|
|
@@ -205,10 +203,17 @@ files:
|
|
|
205
203
|
- lib/servus/extensions/async/errors.rb
|
|
206
204
|
- lib/servus/extensions/async/ext.rb
|
|
207
205
|
- lib/servus/extensions/async/job.rb
|
|
206
|
+
- lib/servus/guard.rb
|
|
207
|
+
- lib/servus/guards.rb
|
|
208
|
+
- lib/servus/guards/falsey_guard.rb
|
|
209
|
+
- lib/servus/guards/presence_guard.rb
|
|
210
|
+
- lib/servus/guards/state_guard.rb
|
|
211
|
+
- lib/servus/guards/truthy_guard.rb
|
|
208
212
|
- lib/servus/helpers/controller_helpers.rb
|
|
209
213
|
- lib/servus/railtie.rb
|
|
210
214
|
- lib/servus/support/errors.rb
|
|
211
215
|
- lib/servus/support/logger.rb
|
|
216
|
+
- lib/servus/support/message_resolver.rb
|
|
212
217
|
- lib/servus/support/rescuer.rb
|
|
213
218
|
- lib/servus/support/response.rb
|
|
214
219
|
- lib/servus/support/validator.rb
|
data/builds/servus-0.0.1.gem
DELETED
|
Binary file
|
data/builds/servus-0.1.1.gem
DELETED
|
Binary file
|
data/builds/servus-0.1.2.gem
DELETED
|
Binary file
|
data/builds/servus-0.1.3.gem
DELETED
|
Binary file
|
data/builds/servus-0.1.4.gem
DELETED
|
Binary file
|
data/builds/servus-0.1.5.gem
DELETED
|
Binary file
|