linked_rails 0.0.3 → 0.0.4.pre.ge1306665a
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/LICENSE +21 -674
- data/app/controllers/linked_rails/actions/objects_controller.rb +9 -0
- data/app/controllers/linked_rails/bulk_controller.rb +71 -21
- data/app/controllers/linked_rails/enum_values_controller.rb +0 -42
- data/app/models/linked_rails/actions/item.rb +64 -55
- data/app/models/linked_rails/actions/list.rb +6 -31
- data/app/models/linked_rails/actions/object.rb +38 -0
- data/app/models/linked_rails/collection/configuration.rb +55 -0
- data/app/models/linked_rails/collection/filter.rb +1 -1
- data/app/models/linked_rails/collection/filter_field.rb +19 -2
- data/app/models/linked_rails/collection/filter_option.rb +1 -1
- data/app/models/linked_rails/collection/filterable.rb +6 -9
- data/app/models/linked_rails/collection/infinite.rb +113 -0
- data/app/models/linked_rails/collection/infinite_view.rb +1 -90
- data/app/models/linked_rails/collection/iri.rb +47 -43
- data/app/models/linked_rails/collection/iri_mapping.rb +15 -7
- data/app/models/linked_rails/collection/paginated.rb +46 -0
- data/app/models/linked_rails/collection/paginated_view.rb +1 -33
- data/app/models/linked_rails/collection/sortable.rb +1 -9
- data/app/models/linked_rails/collection/sorting.rb +1 -1
- data/app/models/linked_rails/collection/view.rb +51 -14
- data/app/models/linked_rails/collection.rb +53 -85
- data/app/models/linked_rails/creative_work.rb +1 -1
- data/app/models/linked_rails/entry_point.rb +8 -5
- data/app/models/linked_rails/enum_value.rb +40 -2
- data/app/models/linked_rails/form/field/association_input.rb +7 -1
- data/app/models/linked_rails/form/field/file_input.rb +1 -0
- data/app/models/linked_rails/form/field/resource_field.rb +2 -0
- data/{lib/linked_rails/enhancements/indexable/model.rb → app/models/linked_rails/form/field/url_input.rb} +3 -3
- data/app/models/linked_rails/form/field.rb +37 -13
- data/app/models/linked_rails/form/field_factory.rb +48 -18
- data/app/models/linked_rails/form/group.rb +4 -6
- data/app/models/linked_rails/form/page.rb +8 -4
- data/app/models/linked_rails/form.rb +16 -21
- data/app/models/linked_rails/manifest.rb +8 -2
- data/app/models/linked_rails/menus/item.rb +10 -13
- data/app/models/linked_rails/menus/list.rb +16 -7
- data/app/models/linked_rails/ontology/base.rb +3 -1
- data/app/models/linked_rails/ontology/class.rb +3 -3
- data/app/models/linked_rails/ontology.rb +5 -5
- data/app/models/linked_rails/property_query.rb +2 -0
- data/app/models/linked_rails/sequence.rb +4 -13
- data/app/models/linked_rails/shacl/property_shape.rb +1 -1
- data/app/models/linked_rails/web_page.rb +0 -4
- data/app/models/linked_rails/web_site.rb +0 -4
- data/app/models/linked_rails/widget.rb +4 -11
- data/app/policies/linked_rails/actions/object_policy.rb +11 -0
- data/app/policies/linked_rails/collection_policy.rb +2 -2
- data/app/serializers/linked_rails/actions/item_serializer.rb +5 -5
- data/app/serializers/linked_rails/actions/object_serializer.rb +9 -0
- data/app/serializers/linked_rails/collection/filter_field_serializer.rb +3 -2
- data/app/serializers/linked_rails/collection/filter_option_serializer.rb +1 -1
- data/app/serializers/linked_rails/collection/filter_serializer.rb +1 -1
- data/app/serializers/linked_rails/collection/sorting_serializer.rb +1 -1
- data/app/serializers/linked_rails/collection/view_serializer.rb +3 -3
- data/app/serializers/linked_rails/collection_serializer.rb +8 -7
- data/app/serializers/linked_rails/condition_serializer.rb +3 -3
- data/app/serializers/linked_rails/entry_point_serializer.rb +3 -3
- data/app/serializers/linked_rails/enum_value_serializer.rb +1 -0
- data/app/serializers/linked_rails/form/field/association_input_serializer.rb +1 -0
- data/app/serializers/linked_rails/form/field/file_input_serializer.rb +11 -0
- data/app/serializers/linked_rails/form/field_serializer.rb +3 -1
- data/app/serializers/linked_rails/form/group_serializer.rb +1 -1
- data/app/serializers/linked_rails/form/page_serializer.rb +1 -1
- data/app/serializers/linked_rails/menus/item_serializer.rb +3 -3
- data/app/serializers/linked_rails/menus/list_serializer.rb +1 -1
- data/app/serializers/linked_rails/ontology_serializer.rb +2 -2
- data/app/serializers/linked_rails/property_query_serializer.rb +7 -0
- data/app/serializers/linked_rails/sequence_serializer.rb +2 -5
- data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +1 -1
- data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +1 -1
- data/app/serializers/linked_rails/shacl/shape_serializer.rb +5 -5
- data/app/serializers/linked_rails/web_page_serializer.rb +3 -3
- data/app/serializers/linked_rails/web_site_serializer.rb +1 -1
- data/app/serializers/linked_rails/widget_serializer.rb +3 -3
- data/lib/generators/linked_rails/install/install_generator.rb +5 -8
- data/lib/generators/linked_rails/install/templates/README +2 -0
- data/lib/generators/linked_rails/install/templates/app_menu_list.rb +36 -7
- data/lib/generators/linked_rails/install/templates/application_menu_list.rb +40 -1
- data/lib/generators/linked_rails/install/templates/initializer.rb +1 -2
- data/lib/generators/linked_rails/install/templates/locales.yml +14 -0
- data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +1 -1
- data/lib/generators/linked_rails/install/templates/vocab.rb +1 -0
- data/lib/generators/linked_rails/install/templates/vocab.yml +2 -2
- data/lib/generators/linked_rails/model/model_generator.rb +0 -1
- data/lib/generators/linked_rails/model/templates/controller.rb.tt +5 -1
- data/lib/generators/linked_rails/model/templates/form.rb.tt +3 -0
- data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +15 -0
- data/lib/generators/linked_rails/model/templates/policy.rb.tt +13 -0
- data/lib/generators/linked_rails/model/templates/serializer.rb.tt +5 -1
- data/lib/linked_rails/active_response/controller/collections.rb +1 -1
- data/lib/linked_rails/active_response/controller/crud_defaults.rb +4 -4
- data/lib/linked_rails/active_response/controller/params.rb +10 -10
- data/lib/linked_rails/active_response/controller.rb +8 -18
- data/lib/linked_rails/active_response/responders/rdf.rb +19 -10
- data/lib/linked_rails/callable_variable.rb +1 -1
- data/lib/linked_rails/collection_params_parser.rb +93 -0
- data/lib/linked_rails/controller/actionable.rb +121 -0
- data/lib/linked_rails/controller/authorization.rb +6 -0
- data/lib/linked_rails/controller/default_actions/create.rb +52 -0
- data/lib/linked_rails/controller/default_actions/destroy.rb +42 -0
- data/lib/linked_rails/controller/default_actions/update.rb +43 -0
- data/lib/linked_rails/controller/delta.rb +78 -0
- data/lib/linked_rails/controller/error_handling.rb +10 -10
- data/lib/linked_rails/controller/rendering.rb +48 -0
- data/lib/linked_rails/controller.rb +24 -4
- data/lib/linked_rails/enhancements/creatable/controller.rb +1 -1
- data/lib/linked_rails/enhancements/destroyable/controller.rb +1 -1
- data/lib/linked_rails/enhancements/updatable/controller.rb +1 -1
- data/lib/linked_rails/enhancements.rb +0 -16
- data/lib/linked_rails/helpers/delta_helper.rb +26 -57
- data/lib/linked_rails/helpers/ontola_actions_helper.rb +2 -2
- data/lib/linked_rails/helpers/resource_helper.rb +4 -2
- data/lib/linked_rails/iri_mapper.rb +17 -39
- data/lib/linked_rails/middleware/error_handling.rb +51 -0
- data/lib/linked_rails/middleware/linked_data_params.rb +30 -151
- data/lib/linked_rails/model/actionable.rb +68 -0
- data/lib/linked_rails/model/collections.rb +201 -39
- data/lib/linked_rails/model/dirty.rb +7 -8
- data/lib/linked_rails/model/enhancements.rb +1 -6
- data/lib/linked_rails/model/filtering.rb +4 -6
- data/lib/linked_rails/model/indexable.rb +6 -16
- data/lib/linked_rails/model/iri.rb +28 -19
- data/lib/linked_rails/model/iri_mapping.rb +37 -8
- data/lib/linked_rails/model/menuable.rb +28 -0
- data/lib/linked_rails/model/serialization.rb +2 -15
- data/lib/linked_rails/model/singularable.rb +57 -0
- data/lib/linked_rails/model/sorting.rb +0 -5
- data/lib/linked_rails/model/tables.rb +26 -0
- data/lib/linked_rails/model.rb +17 -7
- data/lib/linked_rails/params_parser.rb +133 -55
- data/lib/linked_rails/policy/attribute_conditions.rb +2 -2
- data/lib/linked_rails/policy.rb +40 -46
- data/lib/linked_rails/railtie.rb +11 -0
- data/lib/linked_rails/rdf_error.rb +2 -2
- data/lib/linked_rails/renderers.rb +1 -0
- data/lib/linked_rails/routes.rb +38 -22
- data/lib/linked_rails/serializer/actionable.rb +27 -0
- data/lib/linked_rails/serializer/menuable.rb +31 -0
- data/lib/linked_rails/serializer/singularable.rb +26 -0
- data/lib/linked_rails/serializer.rb +28 -11
- data/lib/linked_rails/test_methods.rb +114 -0
- data/lib/linked_rails/translate.rb +31 -9
- data/lib/linked_rails/types/iri_type.rb +37 -0
- data/lib/linked_rails/uri_template.rb +30 -0
- data/lib/linked_rails/version.rb +1 -1
- data/lib/linked_rails/vocab.rb +9 -0
- data/lib/linked_rails.rb +30 -13
- data/lib/rails/welcome_controller.rb +3 -3
- data/lib/rdf/list.rb +9 -0
- data/lib/rdf/query_fix.rb +15 -0
- metadata +57 -33
- data/app/models/linked_rails/actions/default_actions/create.rb +0 -60
- data/app/models/linked_rails/actions/default_actions/destroy.rb +0 -45
- data/app/models/linked_rails/actions/default_actions/update.rb +0 -50
- data/app/models/linked_rails/actions/default_actions.rb +0 -17
- data/lib/generators/linked_rails/install/templates/application_action_list.rb +0 -3
- data/lib/generators/linked_rails/model/templates/action_list.rb.tt +0 -6
- data/lib/linked_rails/enhancements/actionable/model.rb +0 -71
- data/lib/linked_rails/enhancements/actionable/serializer.rb +0 -25
- data/lib/linked_rails/enhancements/creatable/action.rb +0 -15
- data/lib/linked_rails/enhancements/destroyable/action.rb +0 -15
- data/lib/linked_rails/enhancements/destroyable/routing.rb +0 -19
- data/lib/linked_rails/enhancements/menuable/model.rb +0 -36
- data/lib/linked_rails/enhancements/menuable/serializer.rb +0 -33
- data/lib/linked_rails/enhancements/route_concerns.rb +0 -56
- data/lib/linked_rails/enhancements/singularable/controller.rb +0 -43
- data/lib/linked_rails/enhancements/singularable/model.rb +0 -47
- data/lib/linked_rails/enhancements/singularable/serializer.rb +0 -28
- data/lib/linked_rails/enhancements/tableable/model.rb +0 -28
- data/lib/linked_rails/enhancements/updatable/action.rb +0 -15
- data/lib/linked_rails/enhancements/updatable/routing.rb +0 -20
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'pundit'
|
4
4
|
|
5
|
+
require_relative 'collection/configuration'
|
5
6
|
require_relative 'collection/filter'
|
6
7
|
require_relative 'collection/filterable'
|
7
8
|
require_relative 'collection/iri'
|
@@ -9,28 +10,38 @@ require_relative 'collection/iri_mapping'
|
|
9
10
|
require_relative 'collection/sortable'
|
10
11
|
require_relative 'collection/sorting'
|
11
12
|
require_relative 'collection/view'
|
13
|
+
require_relative 'collection/paginated'
|
12
14
|
require_relative 'collection/paginated_view'
|
15
|
+
require_relative 'collection/infinite'
|
13
16
|
require_relative 'collection/infinite_view'
|
14
17
|
|
15
18
|
module LinkedRails
|
16
19
|
class Collection # rubocop:disable Metrics/ClassLength
|
17
20
|
include ActiveModel::Model
|
18
|
-
include LinkedRails::Model::
|
19
|
-
include LinkedRails::Model::
|
21
|
+
include LinkedRails::Model::Actionable
|
22
|
+
include LinkedRails::Model::IRI
|
23
|
+
include LinkedRails::Collection::Configuration
|
20
24
|
include LinkedRails::Collection::Filterable
|
21
|
-
include LinkedRails::Collection::
|
22
|
-
include LinkedRails::Collection::
|
25
|
+
include LinkedRails::Collection::IRI
|
26
|
+
include LinkedRails::Collection::IRIMapping
|
23
27
|
include LinkedRails::Collection::Sortable
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
attr_accessor :association, :association_class, :association_scope, :grid_max_columns, :joins,
|
28
|
-
:name, :page_size, :parent, :part_of, :policy, :user_context, :view
|
29
|
-
attr_writer :association_base, :table_type, :default_display, :default_title, :default_type,
|
30
|
-
:display, :policy_scope, :title, :type, :views
|
29
|
+
attr_accessor :name, :policy, :user_context
|
30
|
+
attr_writer :association_base, :views
|
31
31
|
|
32
32
|
alias id iri
|
33
33
|
|
34
|
+
def initialize(**opts)
|
35
|
+
opts = opts.with_indifferent_access
|
36
|
+
|
37
|
+
%i[association_class iri_template].each do |key|
|
38
|
+
raise("No #{key} given") if opts[key].blank?
|
39
|
+
end
|
40
|
+
opts[:route_key] ||= opts[:association_class].collection_route_key
|
41
|
+
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
34
45
|
def action_list(user_context)
|
35
46
|
@action_list ||= {}
|
36
47
|
@action_list[user_context] ||= association_class.try(:action_list)&.new(
|
@@ -56,21 +67,8 @@ module LinkedRails
|
|
56
67
|
super(options.merge(except: %w[association_class unfiltered_collection collection]))
|
57
68
|
end
|
58
69
|
|
59
|
-
def
|
60
|
-
@
|
61
|
-
end
|
62
|
-
|
63
|
-
def build_child # rubocop:disable Metrics/AbcSize
|
64
|
-
child =
|
65
|
-
parent&.build_child(association_class, user_context: user_context) ||
|
66
|
-
association_class.build_new(parent: parent, user_context: user_context)
|
67
|
-
|
68
|
-
attributes_from_filters = ActionController::Parameters.new(association_class.attributes_from_filters(@filter))
|
69
|
-
permitted_child_keys = Pundit.policy(user_context, child)&.permitted_attributes || []
|
70
|
-
permitted_attributes_from_filters = attributes_from_filters.permit(permitted_child_keys)
|
71
|
-
|
72
|
-
child.assign_attributes(permitted_attributes_from_filters)
|
73
|
-
child
|
70
|
+
def child_resource
|
71
|
+
@child_resource ||= build_child
|
74
72
|
end
|
75
73
|
|
76
74
|
def columns
|
@@ -79,18 +77,10 @@ module LinkedRails
|
|
79
77
|
RDF::List[*columns_list] if columns_list.present?
|
80
78
|
end
|
81
79
|
|
82
|
-
def default_page_size
|
83
|
-
association_class.try(:default_per_page) || 20
|
84
|
-
end
|
85
|
-
|
86
80
|
def default_view
|
87
81
|
@default_view ||= view_with_opts(default_view_opts)
|
88
82
|
end
|
89
83
|
|
90
|
-
def display
|
91
|
-
@display&.to_sym || default_display
|
92
|
-
end
|
93
|
-
|
94
84
|
def first
|
95
85
|
case type
|
96
86
|
when :paginated
|
@@ -110,32 +100,7 @@ module LinkedRails
|
|
110
100
|
|
111
101
|
def new_child(options)
|
112
102
|
attrs = options.merge(new_child_values)
|
113
|
-
self.class.new(attrs)
|
114
|
-
end
|
115
|
-
|
116
|
-
def preview_includes
|
117
|
-
{
|
118
|
-
default_view: default_view.preview_includes,
|
119
|
-
filter_fields: :options,
|
120
|
-
filters: [],
|
121
|
-
sortings: []
|
122
|
-
}
|
123
|
-
end
|
124
|
-
|
125
|
-
def title
|
126
|
-
var = @title || @default_title
|
127
|
-
return var.call(parent) if var.respond_to?(:call)
|
128
|
-
|
129
|
-
var || title_from_translation
|
130
|
-
end
|
131
|
-
|
132
|
-
def title_from_translation
|
133
|
-
plural = association_class.name.tableize
|
134
|
-
I18n.t(
|
135
|
-
"#{plural}.collection.#{@filter&.values&.join('.').presence || name || :default}",
|
136
|
-
count: ->(_opts) { total_count },
|
137
|
-
default: association_class.plural_label
|
138
|
-
)
|
103
|
+
self.class.new(**attrs)
|
139
104
|
end
|
140
105
|
|
141
106
|
def total_count
|
@@ -143,11 +108,7 @@ module LinkedRails
|
|
143
108
|
end
|
144
109
|
|
145
110
|
def total_page_count
|
146
|
-
(total_count /
|
147
|
-
end
|
148
|
-
|
149
|
-
def type
|
150
|
-
@type&.to_sym || default_type
|
111
|
+
(total_count / page_size.to_f).ceil if total_count
|
151
112
|
end
|
152
113
|
|
153
114
|
def unscoped_association
|
@@ -160,21 +121,25 @@ module LinkedRails
|
|
160
121
|
|
161
122
|
def view_with_opts(opts)
|
162
123
|
@views ||= []
|
163
|
-
view =
|
124
|
+
view = collection_view_class.new(**{collection: self, type: type}.merge(opts))
|
164
125
|
@views << view
|
165
126
|
view
|
166
127
|
end
|
167
128
|
|
168
129
|
private
|
169
130
|
|
170
|
-
def
|
171
|
-
|
131
|
+
def build_child
|
132
|
+
child =
|
133
|
+
parent&.build_child(association_class, user_context: user_context) ||
|
134
|
+
association_class.build_new(parent: parent, user_context: user_context)
|
172
135
|
|
173
|
-
|
136
|
+
child.assign_attributes(association_base.where_values_hash) if association_base.respond_to?(:where_values_hash)
|
137
|
+
child.assign_attributes(permitted_attributes_from_filters(child))
|
138
|
+
child
|
174
139
|
end
|
175
140
|
|
176
|
-
def
|
177
|
-
|
141
|
+
def collection_view_class
|
142
|
+
LinkedRails.collection_view_class
|
178
143
|
end
|
179
144
|
|
180
145
|
def default_view_opts
|
@@ -187,30 +152,33 @@ module LinkedRails
|
|
187
152
|
opts
|
188
153
|
end
|
189
154
|
|
190
|
-
def policy_scope
|
191
|
-
return @policy_scope if @policy_scope == false
|
192
|
-
|
193
|
-
@policy_scope = policy ? policy::Scope : Pundit::PolicyFinder.new(filtered_association).scope!
|
194
|
-
end
|
195
|
-
|
196
155
|
def paginated?
|
197
156
|
type == :paginated
|
198
157
|
end
|
199
158
|
|
200
|
-
def
|
201
|
-
return
|
159
|
+
def permitted_attributes_from_filters(child)
|
160
|
+
return {} if @filter.empty?
|
202
161
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
162
|
+
Pundit.policy(user_context, child).try(:permitted_attributes_from_filters, @filter) || {}
|
163
|
+
end
|
164
|
+
|
165
|
+
def title_from_translation
|
166
|
+
plural = association_class.name.tableize
|
167
|
+
|
168
|
+
I18n.t(
|
169
|
+
"#{plural}.collection.#{filter&.values&.join('.').presence || name || :default}",
|
170
|
+
count: ->(_opts) { total_count },
|
171
|
+
default: association_class.plural_label
|
172
|
+
)
|
209
173
|
end
|
210
174
|
|
211
175
|
def new_child_values
|
212
176
|
instance_values
|
213
|
-
.slice(
|
177
|
+
.slice(
|
178
|
+
'iri_template',
|
179
|
+
*LinkedRails::Model::Collections::COLLECTION_STATIC_OPTIONS.keys.map(&:to_s),
|
180
|
+
*LinkedRails::Model::Collections::COLLECTION_CUSTOMIZABLE_OPTIONS.keys.map { |key| "default_#{key}" }
|
181
|
+
)
|
214
182
|
.merge(
|
215
183
|
unfiltered_collection: filtered? ? @unfiltered_collection : self,
|
216
184
|
user_context: user_context
|
@@ -6,7 +6,7 @@ module LinkedRails
|
|
6
6
|
include LinkedRails::Model
|
7
7
|
|
8
8
|
attr_accessor :parent
|
9
|
-
attr_writer :
|
9
|
+
attr_writer :target_url
|
10
10
|
delegate :form, :description, :http_method, :image, :user_context,
|
11
11
|
:resource, :tag, to: :parent
|
12
12
|
|
@@ -16,12 +16,15 @@ module LinkedRails
|
|
16
16
|
form&.form_iri
|
17
17
|
end
|
18
18
|
|
19
|
-
def as_json(_opts
|
19
|
+
def as_json(**_opts)
|
20
20
|
{}
|
21
21
|
end
|
22
22
|
|
23
23
|
def iri_template
|
24
|
-
@iri_template ||= iri_template_with_fragment(
|
24
|
+
@iri_template ||= iri_template_with_fragment(
|
25
|
+
LinkedRails::URITemplate.new(parent.root_relative_iri.to_s),
|
26
|
+
:EntryPoint
|
27
|
+
)
|
25
28
|
end
|
26
29
|
|
27
30
|
def label
|
@@ -30,8 +33,8 @@ module LinkedRails
|
|
30
33
|
value || label_fallback
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
@
|
36
|
+
def target_url
|
37
|
+
@target_url || parent.target_url
|
35
38
|
end
|
36
39
|
|
37
40
|
private
|
@@ -5,14 +5,14 @@ module LinkedRails
|
|
5
5
|
include ActiveModel::Model
|
6
6
|
include LinkedRails::Model
|
7
7
|
|
8
|
-
attr_accessor :attr, :close_match, :exact_match, :group_by, :key, :klass, :type
|
8
|
+
attr_accessor :attr, :close_match, :exact_match, :group_by, :identifier, :key, :klass, :type
|
9
9
|
attr_writer :iri, :label
|
10
10
|
|
11
11
|
def label
|
12
12
|
label_from_variable || LinkedRails.translate(:enum, :label, self)
|
13
13
|
end
|
14
14
|
|
15
|
-
def iri(_opts
|
15
|
+
def iri(**_opts)
|
16
16
|
@iri || iri_with_root(RDF::URI("/enums/#{klass.name.tableize}/#{attr}##{key}"))
|
17
17
|
end
|
18
18
|
|
@@ -29,5 +29,43 @@ module LinkedRails
|
|
29
29
|
def label_from_variable
|
30
30
|
@label.respond_to?(:call) ? @label.call : @label
|
31
31
|
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def class_for_params(params)
|
35
|
+
LinkedRails.linked_models.detect do |klass|
|
36
|
+
klass.to_s == ([params[:module]].compact + [params[:klass]&.singularize]).join('/').classify
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def enum_options(params)
|
41
|
+
serializer_for_params(params)&.enum_options(params[:attribute])
|
42
|
+
end
|
43
|
+
|
44
|
+
def requested_resource(opts, _user_context)
|
45
|
+
options = enum_options(opts[:params])
|
46
|
+
|
47
|
+
return unless options
|
48
|
+
|
49
|
+
LinkedRails::Sequence.new(
|
50
|
+
options.values,
|
51
|
+
id: sanitized_sequence_iri(opts[:iri]),
|
52
|
+
scope: LinkedRails::EnumValuePolicy::Scope
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def sanitized_sequence_iri(raw_iri)
|
57
|
+
iri = RDF::URI(raw_iri)
|
58
|
+
iri.query = nil
|
59
|
+
iri.fragment = nil
|
60
|
+
iri.path = iri.path.split('.').first
|
61
|
+
iri
|
62
|
+
end
|
63
|
+
|
64
|
+
def serializer_for_params(params)
|
65
|
+
klass = class_for_params(params)
|
66
|
+
|
67
|
+
RDF::Serializers.serializer_for(klass) if klass
|
68
|
+
end
|
69
|
+
end
|
32
70
|
end
|
33
71
|
end
|
@@ -9,7 +9,13 @@ module LinkedRails
|
|
9
9
|
def datatype; end
|
10
10
|
|
11
11
|
def nested_form
|
12
|
-
@nested_form ||=
|
12
|
+
@nested_form ||= target_class.form_class
|
13
|
+
end
|
14
|
+
|
15
|
+
def target_class
|
16
|
+
return @target_class if @target_class
|
17
|
+
|
18
|
+
klass_name.constantize unless form.abstract_form
|
13
19
|
end
|
14
20
|
|
15
21
|
private
|
@@ -2,25 +2,27 @@
|
|
2
2
|
|
3
3
|
module LinkedRails
|
4
4
|
class Form
|
5
|
-
class Field < LinkedRails::Resource
|
6
|
-
attr_writer :
|
7
|
-
:description,
|
5
|
+
class Field < LinkedRails::Resource # rubocop:disable Metrics/ClassLength
|
6
|
+
attr_writer :description,
|
8
7
|
:helper_text,
|
9
8
|
:label,
|
9
|
+
:max_inclusive,
|
10
10
|
:max_length,
|
11
11
|
:min_count,
|
12
|
+
:min_inclusive,
|
12
13
|
:min_length,
|
13
|
-
:sh_in,
|
14
14
|
:pattern,
|
15
|
-
:path
|
16
|
-
|
15
|
+
:path,
|
16
|
+
:placeholder,
|
17
|
+
:sh_in,
|
18
|
+
:start_adornment
|
19
|
+
attr_accessor :datatype,
|
20
|
+
:default_value,
|
17
21
|
:max_count,
|
18
22
|
:max_count_prop,
|
19
|
-
:max_inclusive,
|
20
23
|
:max_inclusive_prop,
|
21
24
|
:max_length_prop,
|
22
25
|
:min_count_prop,
|
23
|
-
:min_inclusive,
|
24
26
|
:min_inclusive_prop,
|
25
27
|
:min_length_prop,
|
26
28
|
:model_attribute,
|
@@ -31,9 +33,6 @@ module LinkedRails
|
|
31
33
|
:validators,
|
32
34
|
:sh_in_prop,
|
33
35
|
:key
|
34
|
-
def datatype
|
35
|
-
@datatype || raise("No datatype found for #{key} in #{form.name}")
|
36
|
-
end
|
37
36
|
|
38
37
|
def description
|
39
38
|
description_from_attribute || description_fallback
|
@@ -43,6 +42,10 @@ module LinkedRails
|
|
43
42
|
helper_text_from_attribute || helper_text_fallback
|
44
43
|
end
|
45
44
|
|
45
|
+
def max_inclusive
|
46
|
+
@max_inclusive || validators[:max_inclusive]
|
47
|
+
end
|
48
|
+
|
46
49
|
def max_length
|
47
50
|
@max_length || validators[:max_length]
|
48
51
|
end
|
@@ -51,6 +54,10 @@ module LinkedRails
|
|
51
54
|
@min_count || (validators[:presence] ? 1 : nil)
|
52
55
|
end
|
53
56
|
|
57
|
+
def min_inclusive
|
58
|
+
@min_inclusive || validators[:min_inclusive]
|
59
|
+
end
|
60
|
+
|
54
61
|
def min_length
|
55
62
|
@min_length || validators[:min_length]
|
56
63
|
end
|
@@ -72,12 +79,20 @@ module LinkedRails
|
|
72
79
|
true
|
73
80
|
end
|
74
81
|
|
82
|
+
def placeholder
|
83
|
+
placeholder_from_attribute || placeholder_fallback
|
84
|
+
end
|
85
|
+
|
75
86
|
def sh_in
|
76
87
|
return validators[:sh_in] if @sh_in.blank?
|
77
88
|
|
78
89
|
@sh_in.respond_to?(:call) ? @sh_in.call : @sh_in
|
79
90
|
end
|
80
91
|
|
92
|
+
def start_adornment
|
93
|
+
@start_adornment.respond_to?(:call) ? @start_adornment.call : @start_adornment
|
94
|
+
end
|
95
|
+
|
81
96
|
private
|
82
97
|
|
83
98
|
def description_from_attribute
|
@@ -101,12 +116,21 @@ module LinkedRails
|
|
101
116
|
end
|
102
117
|
|
103
118
|
def label_fallback
|
104
|
-
|
105
|
-
|
119
|
+
LinkedRails.translate(:field, :label, self, false).presence || label_from_property
|
120
|
+
end
|
106
121
|
|
122
|
+
def label_from_property
|
107
123
|
LinkedRails.translate(:property, :label, path) if path
|
108
124
|
end
|
109
125
|
|
126
|
+
def placeholder_from_attribute
|
127
|
+
@placeholder.respond_to?(:call) ? @placeholder.call : @placeholder
|
128
|
+
end
|
129
|
+
|
130
|
+
def placeholder_fallback
|
131
|
+
LinkedRails.translate(:field, :placeholder, self, false)
|
132
|
+
end
|
133
|
+
|
110
134
|
class << self
|
111
135
|
def iri
|
112
136
|
Vocab.form[name.demodulize]
|
@@ -3,10 +3,17 @@
|
|
3
3
|
module LinkedRails
|
4
4
|
class Form
|
5
5
|
class FieldFactory # rubocop:disable Metrics/ClassLength
|
6
|
+
DATABASE_ERRORS = [
|
7
|
+
'PG::ConnectionBad'.safe_constantize,
|
8
|
+
ActiveRecord::StatementInvalid,
|
9
|
+
ActiveRecord::ConnectionNotEstablished
|
10
|
+
].compact.freeze
|
6
11
|
MAX_STR_LEN = 255
|
7
12
|
VALIDATOR_SELECTORS = [
|
8
13
|
[:min_length, ActiveModel::Validations::LengthValidator, :minimum],
|
14
|
+
[:min_inclusive, ActiveModel::Validations::NumericalityValidator, :greater_than_or_equal_to],
|
9
15
|
[:max_length, ActiveModel::Validations::LengthValidator, :maximum],
|
16
|
+
[:max_inclusive, ActiveModel::Validations::NumericalityValidator, :less_than_or_equal_to],
|
10
17
|
[:pattern, ActiveModel::Validations::FormatValidator, :with],
|
11
18
|
[:presence, ActiveModel::Validations::PresenceValidator, nil],
|
12
19
|
[:sh_in, ActiveModel::Validations::InclusionValidator, :in]
|
@@ -15,7 +22,8 @@ module LinkedRails
|
|
15
22
|
|
16
23
|
attr_accessor :field_options, :form, :key
|
17
24
|
|
18
|
-
delegate :
|
25
|
+
delegate :abstract_form,
|
26
|
+
:form_options_iri,
|
19
27
|
:model_class,
|
20
28
|
:model_policy!,
|
21
29
|
:serializer_attributes,
|
@@ -24,12 +32,21 @@ module LinkedRails
|
|
24
32
|
to: :form
|
25
33
|
|
26
34
|
def condition_or_field
|
27
|
-
@condition_or_field
|
35
|
+
return @condition_or_field if instance_variable_defined?(:@condition_or_field)
|
36
|
+
|
37
|
+
alternatives = node_shapes_for(
|
28
38
|
key,
|
29
|
-
field,
|
30
39
|
property: field_options[:if] || [],
|
31
40
|
sh_not: field_options[:unless] || []
|
32
41
|
)
|
42
|
+
@condition_or_field =
|
43
|
+
if alternatives.count == 1
|
44
|
+
Condition.new(shape: alternatives.first, pass: field)
|
45
|
+
elsif alternatives.count.positive?
|
46
|
+
Condition.new(shape: SHACL::NodeShape.new(or: alternatives), pass: field)
|
47
|
+
else
|
48
|
+
field
|
49
|
+
end
|
33
50
|
end
|
34
51
|
|
35
52
|
private
|
@@ -45,8 +62,7 @@ module LinkedRails
|
|
45
62
|
end
|
46
63
|
|
47
64
|
def attr_to_datatype # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
48
|
-
|
49
|
-
case attribute_type(name)
|
65
|
+
case attribute_type
|
50
66
|
when :string, :text
|
51
67
|
Vocab.xsd.string
|
52
68
|
when :integer
|
@@ -58,22 +74,26 @@ module LinkedRails
|
|
58
74
|
when :boolean
|
59
75
|
Vocab.xsd.boolean
|
60
76
|
when :decimal
|
61
|
-
decimal_data_type(
|
77
|
+
decimal_data_type(attribute_name)
|
62
78
|
when :file
|
63
79
|
Vocab.ll[:blob]
|
64
80
|
else
|
65
|
-
Vocab.xsd.string if model_class.try(:defined_enums)&.key?(
|
81
|
+
Vocab.xsd.string if model_class.try(:defined_enums)&.key?(attribute_name)
|
66
82
|
end
|
67
83
|
end
|
68
84
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
85
|
+
def attribute_name
|
86
|
+
serializer_attribute&.key&.to_s || key.to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def attribute_type
|
90
|
+
model_class.try(:attribute_types).try(:[], attribute_name)&.type
|
91
|
+
rescue *DATABASE_ERRORS
|
72
92
|
:string
|
73
93
|
end
|
74
94
|
|
75
95
|
def attribute_validators
|
76
|
-
@attribute_validators ||= model_class
|
96
|
+
@attribute_validators ||= model_class&.validators&.select { |v| v.attributes.include?(model_attribute) }
|
77
97
|
end
|
78
98
|
|
79
99
|
def datatype
|
@@ -143,7 +163,7 @@ module LinkedRails
|
|
143
163
|
when Vocab.ontola['datatype/postalRange']
|
144
164
|
return Form::Field::PostalRangeInput
|
145
165
|
else
|
146
|
-
|
166
|
+
attribute_type == :text ? Form::Field::TextAreaInput : Form::Field::TextInput
|
147
167
|
end
|
148
168
|
end
|
149
169
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
@@ -168,6 +188,15 @@ module LinkedRails
|
|
168
188
|
@model_attribute ||= (model_class.try(:attribute_alias, key) || key).to_sym
|
169
189
|
end
|
170
190
|
|
191
|
+
def node_shapes_for(attr, property: [], sh_not: [])
|
192
|
+
alternatives = abstract_form ? [] : model_policy!.condition_alternatives(attr, field.permission_required?)
|
193
|
+
alternatives = [[]] if alternatives.empty? && (property.any? || sh_not.any?)
|
194
|
+
|
195
|
+
alternatives.map do |props|
|
196
|
+
SHACL::NodeShape.new(property: props + property, sh_not: sh_not)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
171
200
|
def normalized_key(key)
|
172
201
|
return key.to_s[0...-3].to_sym if key.to_s.ends_with?('_id')
|
173
202
|
return key.to_s[0...-4].pluralize.to_sym if key.to_s.ends_with?('_ids')
|
@@ -197,14 +226,15 @@ module LinkedRails
|
|
197
226
|
def validator(klass, option_key)
|
198
227
|
matched_validator = validator_by_class(klass)
|
199
228
|
|
200
|
-
option_key ? matched_validator&.options.try(:[], option_key) : matched_validator.present?
|
229
|
+
value = option_key ? matched_validator&.options.try(:[], option_key) : matched_validator.present?
|
230
|
+
|
231
|
+
value unless value.respond_to?(:call)
|
201
232
|
end
|
202
233
|
|
203
234
|
def validator_by_class(klass)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
matched_validator if matched_validator.options[:if].blank? && matched_validator.options[:unless].blank?
|
235
|
+
attribute_validators&.detect do |validator|
|
236
|
+
validator.is_a?(klass) && validator.options[:if].blank? && validator.options[:unless].blank?
|
237
|
+
end
|
208
238
|
end
|
209
239
|
|
210
240
|
def validators
|
@@ -212,7 +242,7 @@ module LinkedRails
|
|
212
242
|
VALIDATOR_SELECTORS.map do |key, klass, option_key|
|
213
243
|
[key, validator(klass, option_key)]
|
214
244
|
end
|
215
|
-
]
|
245
|
+
].compact
|
216
246
|
end
|
217
247
|
end
|
218
248
|
end
|
@@ -6,19 +6,17 @@ module LinkedRails
|
|
6
6
|
attr_accessor :fields, :collapsible, :hidden, :footer
|
7
7
|
attr_writer :description, :key, :label
|
8
8
|
|
9
|
-
def initialize(attrs
|
10
|
-
super(attrs)
|
9
|
+
def initialize(**attrs)
|
10
|
+
super(**attrs)
|
11
11
|
self.fields = []
|
12
12
|
end
|
13
13
|
|
14
14
|
def description
|
15
|
-
@description
|
16
|
-
@description
|
15
|
+
@description.respond_to?(:call) ? @description.call : @description
|
17
16
|
end
|
18
17
|
|
19
18
|
def label
|
20
|
-
@label
|
21
|
-
@label
|
19
|
+
@label.respond_to?(:call) ? @label.call : @label
|
22
20
|
end
|
23
21
|
|
24
22
|
def rdf_type
|