Module: Feat::Datafile
- Defined in:
- lib/feat/datafile.rb
Overview
Wire-format types. JSON field names mirror @feathq/datafile-schema exactly (camelCase) — ‘from_json` keeps the hash keys, no rekeying.
Defined Under Namespace
Classes: ConditionGroupSpec, ConditionSpec, ContextKindSpec, File, FlagSpec, Rollout, RolloutVariation, RuleSpec, SegmentRuleSpec, SegmentSpec, TargetSpec, VariationSpec
Class Method Summary
collapse
Class Method Details
.build_flag(d) ⇒ Object
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
# File 'lib/feat/datafile.rb', line 82
def self.build_flag(d)
FlagSpec.new(
id: d["id"],
key: d["key"],
valueType: d["valueType"],
salt: d["salt"],
archived: d["archived"],
isEnabled: d["isEnabled"],
offVariationId: d["offVariationId"],
defaultVariationId: d["defaultVariationId"],
defaultRollout: build_rollout(d["defaultRollout"]),
defaultBucketingContextKindKey: d["defaultBucketingContextKindKey"],
variations: d["variations"].map { |v| VariationSpec.new(**symbolize(v)) },
targets: d["targets"].map { |t| TargetSpec.new(**symbolize(t)) },
rules: d["rules"].map { |r| build_rule(r) }
)
end
|
.build_rollout(d) ⇒ Object
112
113
114
115
116
117
118
119
|
# File 'lib/feat/datafile.rb', line 112
def self.build_rollout(d)
return nil if d.nil?
Rollout.new(
bucketingContextKindKey: d["bucketingContextKindKey"],
variations: d["variations"].map { |v| RolloutVariation.new(**symbolize(v)) }
)
end
|
.build_rule(d) ⇒ Object
100
101
102
103
104
105
106
107
108
109
110
|
# File 'lib/feat/datafile.rb', line 100
def self.build_rule(d)
RuleSpec.new(
id: d["id"],
bucketingContextKindKey: d["bucketingContextKindKey"],
variationId: d["variationId"],
rollout: build_rollout(d["rollout"]),
groups: d["groups"].map { |g|
ConditionGroupSpec.new(conditions: g["conditions"].map { |c| ConditionSpec.new(**symbolize(c)) })
}
)
end
|
.build_segment(d) ⇒ Object
121
122
123
124
125
126
127
128
|
# File 'lib/feat/datafile.rb', line 121
def self.build_segment(d)
SegmentSpec.new(
key: d["key"],
rules: d["rules"].map { |r|
SegmentRuleSpec.new(conditions: r["conditions"].map { |c| ConditionSpec.new(**symbolize(c)) })
}
)
end
|
.from_json(data) ⇒ Object
Parse a wire-format hash (typically JSON.parse output) into a Datafile::File. Hash keys must already be string-keyed (default for JSON.parse).
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/feat/datafile.rb', line 37
def self.from_json(data)
File.new(
schemaVersion: data["schemaVersion"],
envId: data["envId"],
envKey: data["envKey"],
projectId: data["projectId"],
version: data["version"],
etag: data["etag"],
generatedAt: data["generatedAt"],
flags: data["flags"].each_with_object({}) { |(k, v), o| o[k] = build_flag(v) },
segments: (data["segments"] || {}).each_with_object({}) { |(k, v), o| o[k] = build_segment(v) },
contextKinds: (data["contextKinds"] || {}).each_with_object({}) { |(k, v), o| o[k] = ContextKindSpec.new(**symbolize(v)) }
)
end
|
.merge_patch(current, patch) ⇒ Object
Merge a patch delta onto an existing File and return a new File. Pure: current is not mutated. Added or changed flags/segments are built from their wire objects and override by key; removed keys are dropped. version, etag, and generatedAt advance to the patch’s values (etag and generatedAt fall back to the current ones when the patch omits them). Raises if a flag or segment object is malformed; the caller treats that as a no-op and ignores the patch.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/feat/datafile.rb', line 59
def self.merge_patch(current, patch)
flags = current.flags.dup
(patch["flags"] || {}).each { |k, v| flags[k] = build_flag(v) }
(patch["removedFlags"] || []).each { |k| flags.delete(k) }
segments = current.segments.dup
(patch["segments"] || {}).each { |k, v| segments[k] = build_segment(v) }
(patch["removedSegments"] || []).each { |k| segments.delete(k) }
File.new(
schemaVersion: current.schemaVersion,
envId: current.envId,
envKey: current.envKey,
projectId: current.projectId,
version: patch["to"],
etag: patch["etag"] || current.etag,
generatedAt: patch["generatedAt"] || current.generatedAt,
flags: flags,
segments: segments,
contextKinds: current.contextKinds
)
end
|
.symbolize(h) ⇒ Object
130
131
132
|
# File 'lib/feat/datafile.rb', line 130
def self.symbolize(h)
h.each_with_object({}) { |(k, v), o| o[k.to_sym] = v }
end
|