-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfield.rb
More file actions
172 lines (139 loc) · 4.61 KB
/
field.rb
File metadata and controls
172 lines (139 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
class Schema
class Field
class NestedFieldNotSupportedError < StandardError; end
attr_reader :name, :schema
include Schema::Field::Configuration
include Schema::Field::Translations
def initialize(name, schema)
@name = name
@schema = schema
end
def to_s
name
end
def component_class
class_name = "Edition::Details::Fields::#{component_name.camelize}Component"
class_name.constantize
rescue NameError
raise("Component #{class_name} not found")
end
def type
@type ||= properties.fetch("type", "").inquiry
end
def datetime_format?
properties["format"] == "date-time"
end
def enum_values
@enum_values ||= properties["enum"]
end
def default_value
@default_value ||= properties["default"]
end
def nested_fields
if type.object?
embedded_schema = Schema::EmbeddedSchema.new(name, properties, schema)
embedded_schema.fields
elsif type.array? && properties["items"]["type"] == "object"
embedded_schema = Schema::EmbeddedSchema.new(name, properties["items"], schema, is_array: true)
embedded_schema.fields
end
end
def all_nested_fields
return [] if nested_fields.nil?
collected = nested_fields.dup
nested_fields.each do |field|
collected.concat(field.nested_fields) if field.nested_fields.present?
end
collected
end
def nested_field(nested_field_name)
raise(ArgumentError, "Provide the name of a nested field") if nested_field_name.blank?
raise_nested_field_not_supported_error_for(nested_field_name) if nested_fields.nil?
nested_fields.find { |field| field.name == nested_field_name }
end
def array_items
properties.fetch("items", nil)&.tap do |array_items|
if array_items["type"] == "object"
array_items["properties"] = array_items["properties"].sort_by { |k, _v|
field_ordering_rule.find_index(k) || Float::INFINITY
}.to_h
end
end
end
def is_required?
schema.required_fields.include?(name)
end
def name_attribute(index = nil)
output = "edition[details]"
parent_schemas.each { |parent_schema| output += parent_schema.html_name_part(index) }
output + name_attribute_part(index)
end
def name_attribute_part(index = nil)
name_part = "[#{name}]"
name_part += "[#{index}]" if type == "array"
name_part
end
def id_attribute(indexes = [])
output = "edition_details"
parent_schemas.each do |parent_schema|
index = parent_schema.is_array? ? indexes.shift : nil
output += parent_schema.html_id_part(index)
end
output + id_attribute_part(indexes.shift)
end
def id_attribute_part(index = nil)
id_part = "_#{name}"
id_part += "_#{index}" if type == "array" && index.present?
id_part
end
def error_key(indexes = [])
id_attribute(indexes).delete_prefix("edition_")
end
def value_lookup_path(index = nil)
path = []
parent_schemas.each { |parent_schema| path << parent_schema.value_lookup_parts(index) }
path << name
path << index if type == "array"
path.flatten
end
def permitted_params
if type.array? && nested_fields.present?
{ name => [*nested_fields.map(&:permitted_params), "_destroy"] || [] }
elsif type.array?
{ name => [*array_items["properties"]&.keys, "_destroy"] || [] }
elsif datetime_format?
(1..5).map { |i| "#{name}(#{i}i)" }
elsif nested_fields.present?
{ name => nested_fields.map(&:permitted_params) }
else
name
end
end
private
def raise_nested_field_not_supported_error_for(nested_field_name)
error_message =
%~
Field '#{name}' (type: '#{type.presence || 'missing'}') does not support nested fields.
Cannot look up nested field '#{nested_field_name}'.
Only fields with type 'object' or 'array' (of objects) have nested fields.
Schema properties: #{properties}
~.gsub(/\s+/, " ").strip
raise NestedFieldNotSupportedError, error_message
end
def properties
@properties ||= schema.body.dig("properties", name) || {}
end
def root_schema
@root_schema ||= parent_schemas.any? ? parent_schemas[0].parent_schema : schema
end
def parent_schemas
@parent_schemas ||= [].tap { |parents|
current = schema
while current.respond_to?(:parent_schema)
parents << current
current = current.parent_schema
end
}.reverse
end
end
end