linked_rails 0.0.1 → 0.0.4.pre.g1faca9643

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.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -674
  3. data/app/controllers/linked_rails/actions/objects_controller.rb +9 -0
  4. data/app/controllers/linked_rails/bulk_controller.rb +105 -22
  5. data/app/controllers/linked_rails/enum_values_controller.rb +0 -42
  6. data/app/models/linked_rails/actions/item.rb +64 -55
  7. data/app/models/linked_rails/actions/list.rb +6 -31
  8. data/app/models/linked_rails/actions/object.rb +38 -0
  9. data/app/models/linked_rails/collection/configuration.rb +55 -0
  10. data/app/models/linked_rails/collection/filter.rb +1 -1
  11. data/app/models/linked_rails/collection/filter_field.rb +19 -2
  12. data/app/models/linked_rails/collection/filter_option.rb +1 -1
  13. data/app/models/linked_rails/collection/filterable.rb +6 -9
  14. data/app/models/linked_rails/collection/infinite.rb +113 -0
  15. data/app/models/linked_rails/collection/infinite_view.rb +1 -90
  16. data/app/models/linked_rails/collection/iri.rb +47 -43
  17. data/app/models/linked_rails/collection/iri_mapping.rb +15 -7
  18. data/app/models/linked_rails/collection/paginated.rb +46 -0
  19. data/app/models/linked_rails/collection/paginated_view.rb +1 -33
  20. data/app/models/linked_rails/collection/sortable.rb +1 -9
  21. data/app/models/linked_rails/collection/sorting.rb +1 -1
  22. data/app/models/linked_rails/collection/view.rb +51 -14
  23. data/app/models/linked_rails/collection.rb +53 -85
  24. data/app/models/linked_rails/creative_work.rb +1 -1
  25. data/app/models/linked_rails/entry_point.rb +8 -5
  26. data/app/models/linked_rails/enum_value.rb +40 -2
  27. data/app/models/linked_rails/form/field/association_input.rb +7 -1
  28. data/app/models/linked_rails/form/field/file_input.rb +1 -0
  29. data/app/models/linked_rails/form/field/resource_field.rb +2 -0
  30. data/{lib/linked_rails/enhancements/indexable/model.rb → app/models/linked_rails/form/field/url_input.rb} +3 -3
  31. data/app/models/linked_rails/form/field.rb +37 -13
  32. data/app/models/linked_rails/form/field_factory.rb +48 -18
  33. data/app/models/linked_rails/form/group.rb +4 -6
  34. data/app/models/linked_rails/form/page.rb +8 -4
  35. data/app/models/linked_rails/form.rb +17 -21
  36. data/app/models/linked_rails/manifest.rb +102 -22
  37. data/app/models/linked_rails/menus/item.rb +10 -13
  38. data/app/models/linked_rails/menus/list.rb +16 -7
  39. data/app/models/linked_rails/ontology/base.rb +3 -1
  40. data/app/models/linked_rails/ontology/class.rb +3 -3
  41. data/app/models/linked_rails/ontology.rb +6 -5
  42. data/app/models/linked_rails/property_query.rb +2 -0
  43. data/app/models/linked_rails/sequence.rb +4 -13
  44. data/app/models/linked_rails/shacl/property_shape.rb +1 -1
  45. data/app/models/linked_rails/web_page.rb +0 -4
  46. data/app/models/linked_rails/web_site.rb +0 -4
  47. data/app/models/linked_rails/widget.rb +4 -11
  48. data/app/policies/linked_rails/actions/object_policy.rb +11 -0
  49. data/app/policies/linked_rails/collection_policy.rb +2 -2
  50. data/app/policies/linked_rails/form_policy.rb +13 -0
  51. data/app/policies/linked_rails/ontology_policy.rb +13 -0
  52. data/app/serializers/linked_rails/actions/item_serializer.rb +5 -5
  53. data/app/serializers/linked_rails/actions/object_serializer.rb +9 -0
  54. data/app/serializers/linked_rails/collection/filter_field_serializer.rb +3 -2
  55. data/app/serializers/linked_rails/collection/filter_option_serializer.rb +1 -1
  56. data/app/serializers/linked_rails/collection/filter_serializer.rb +1 -1
  57. data/app/serializers/linked_rails/collection/sorting_serializer.rb +1 -1
  58. data/app/serializers/linked_rails/collection/view_serializer.rb +3 -3
  59. data/app/serializers/linked_rails/collection_serializer.rb +8 -7
  60. data/app/serializers/linked_rails/condition_serializer.rb +3 -3
  61. data/app/serializers/linked_rails/entry_point_serializer.rb +3 -3
  62. data/app/serializers/linked_rails/enum_value_serializer.rb +1 -0
  63. data/app/serializers/linked_rails/form/field/association_input_serializer.rb +1 -0
  64. data/app/serializers/linked_rails/form/field/file_input_serializer.rb +11 -0
  65. data/app/serializers/linked_rails/form/field_serializer.rb +3 -1
  66. data/app/serializers/linked_rails/form/group_serializer.rb +1 -1
  67. data/app/serializers/linked_rails/form/page_serializer.rb +1 -1
  68. data/app/serializers/linked_rails/menus/item_serializer.rb +3 -3
  69. data/app/serializers/linked_rails/menus/list_serializer.rb +1 -1
  70. data/app/serializers/linked_rails/ontology_serializer.rb +2 -2
  71. data/app/serializers/linked_rails/property_query_serializer.rb +7 -0
  72. data/app/serializers/linked_rails/sequence_serializer.rb +2 -5
  73. data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +1 -1
  74. data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +1 -1
  75. data/app/serializers/linked_rails/shacl/shape_serializer.rb +5 -5
  76. data/app/serializers/linked_rails/web_page_serializer.rb +3 -3
  77. data/app/serializers/linked_rails/web_site_serializer.rb +1 -1
  78. data/app/serializers/linked_rails/widget_serializer.rb +3 -3
  79. data/app/workers/linked_rails/invalidation_stream_worker.rb +16 -0
  80. data/lib/generators/linked_rails/install/install_generator.rb +7 -8
  81. data/lib/generators/linked_rails/install/templates/README +7 -0
  82. data/lib/generators/linked_rails/install/templates/app_menu_list.rb +36 -7
  83. data/lib/generators/linked_rails/install/templates/application_menu_list.rb +40 -1
  84. data/lib/generators/linked_rails/install/templates/initializer.rb +1 -2
  85. data/lib/generators/linked_rails/install/templates/locales.yml +16 -0
  86. data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +1 -1
  87. data/lib/generators/linked_rails/install/templates/vocab.rb +1 -0
  88. data/lib/generators/linked_rails/install/templates/vocab.yml +2 -2
  89. data/lib/generators/linked_rails/model/model_generator.rb +0 -1
  90. data/lib/generators/linked_rails/model/templates/controller.rb.tt +5 -1
  91. data/lib/generators/linked_rails/model/templates/form.rb.tt +3 -0
  92. data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +15 -0
  93. data/lib/generators/linked_rails/model/templates/policy.rb.tt +13 -0
  94. data/lib/generators/linked_rails/model/templates/serializer.rb.tt +5 -1
  95. data/lib/linked_rails/active_response/controller/collections.rb +1 -1
  96. data/lib/linked_rails/active_response/controller/crud_defaults.rb +4 -4
  97. data/lib/linked_rails/active_response/controller/params.rb +10 -10
  98. data/lib/linked_rails/active_response/controller.rb +8 -18
  99. data/lib/linked_rails/active_response/responders/rdf.rb +19 -10
  100. data/lib/linked_rails/callable_variable.rb +1 -1
  101. data/lib/linked_rails/collection_params_parser.rb +93 -0
  102. data/lib/linked_rails/controller/actionable.rb +121 -0
  103. data/lib/linked_rails/controller/authorization.rb +6 -0
  104. data/lib/linked_rails/controller/default_actions/create.rb +52 -0
  105. data/lib/linked_rails/controller/default_actions/destroy.rb +42 -0
  106. data/lib/linked_rails/controller/default_actions/update.rb +43 -0
  107. data/lib/linked_rails/controller/delta.rb +58 -0
  108. data/lib/linked_rails/controller/error_handling.rb +14 -7
  109. data/lib/linked_rails/controller/rendering.rb +48 -0
  110. data/lib/linked_rails/controller.rb +24 -4
  111. data/lib/linked_rails/enhanceable.rb +1 -1
  112. data/lib/linked_rails/enhancements/creatable/controller.rb +1 -1
  113. data/lib/linked_rails/enhancements/destroyable/controller.rb +1 -1
  114. data/lib/linked_rails/enhancements/updatable/controller.rb +1 -1
  115. data/lib/linked_rails/enhancements.rb +0 -16
  116. data/lib/linked_rails/errors/forbidden.rb +37 -0
  117. data/lib/linked_rails/errors.rb +3 -0
  118. data/lib/linked_rails/helpers/delta_helper.rb +26 -57
  119. data/lib/linked_rails/helpers/ontola_actions_helper.rb +2 -2
  120. data/lib/linked_rails/helpers/resource_helper.rb +11 -2
  121. data/lib/linked_rails/iri_mapper.rb +17 -39
  122. data/lib/linked_rails/middleware/error_handling.rb +51 -0
  123. data/lib/linked_rails/middleware/linked_data_params.rb +30 -151
  124. data/lib/linked_rails/model/actionable.rb +68 -0
  125. data/lib/linked_rails/model/cacheable.rb +45 -0
  126. data/lib/linked_rails/model/collections.rb +201 -39
  127. data/lib/linked_rails/model/dirty.rb +6 -18
  128. data/lib/linked_rails/model/enhancements.rb +1 -6
  129. data/lib/linked_rails/model/filtering.rb +4 -6
  130. data/lib/linked_rails/model/indexable.rb +6 -16
  131. data/lib/linked_rails/model/iri.rb +29 -19
  132. data/lib/linked_rails/model/iri_mapping.rb +37 -8
  133. data/lib/linked_rails/model/menuable.rb +28 -0
  134. data/lib/linked_rails/model/serialization.rb +2 -15
  135. data/lib/linked_rails/model/singularable.rb +57 -0
  136. data/lib/linked_rails/model/sorting.rb +0 -5
  137. data/lib/linked_rails/model/tables.rb +26 -0
  138. data/lib/linked_rails/model.rb +18 -7
  139. data/lib/linked_rails/params_parser.rb +131 -54
  140. data/lib/linked_rails/policy/attribute_conditions.rb +2 -2
  141. data/lib/linked_rails/policy.rb +44 -46
  142. data/lib/linked_rails/railtie.rb +11 -0
  143. data/lib/linked_rails/rdf_error.rb +2 -2
  144. data/lib/linked_rails/renderers.rb +1 -0
  145. data/lib/linked_rails/routes.rb +38 -22
  146. data/lib/linked_rails/serializer/actionable.rb +27 -0
  147. data/lib/linked_rails/serializer/menuable.rb +31 -0
  148. data/lib/linked_rails/serializer/singularable.rb +26 -0
  149. data/lib/linked_rails/serializer.rb +28 -11
  150. data/lib/linked_rails/storage.rb +32 -0
  151. data/lib/linked_rails/test_methods.rb +114 -0
  152. data/lib/linked_rails/translate.rb +31 -9
  153. data/lib/linked_rails/types/iri_type.rb +37 -0
  154. data/lib/linked_rails/uri_template.rb +30 -0
  155. data/lib/linked_rails/url.rb +11 -0
  156. data/lib/linked_rails/version.rb +1 -1
  157. data/lib/linked_rails/vocab.rb +9 -0
  158. data/lib/linked_rails.rb +40 -14
  159. data/lib/rails/welcome_controller.rb +3 -2
  160. data/lib/rdf/list.rb +9 -0
  161. data/lib/rdf/query_fix.rb +15 -0
  162. metadata +80 -33
  163. data/app/models/linked_rails/actions/default_actions/create.rb +0 -60
  164. data/app/models/linked_rails/actions/default_actions/destroy.rb +0 -45
  165. data/app/models/linked_rails/actions/default_actions/update.rb +0 -50
  166. data/app/models/linked_rails/actions/default_actions.rb +0 -17
  167. data/lib/generators/linked_rails/install/templates/application_action_list.rb +0 -3
  168. data/lib/generators/linked_rails/model/templates/action_list.rb.tt +0 -6
  169. data/lib/linked_rails/enhancements/actionable/model.rb +0 -71
  170. data/lib/linked_rails/enhancements/actionable/serializer.rb +0 -25
  171. data/lib/linked_rails/enhancements/creatable/action.rb +0 -15
  172. data/lib/linked_rails/enhancements/destroyable/action.rb +0 -15
  173. data/lib/linked_rails/enhancements/destroyable/routing.rb +0 -19
  174. data/lib/linked_rails/enhancements/menuable/model.rb +0 -36
  175. data/lib/linked_rails/enhancements/menuable/serializer.rb +0 -33
  176. data/lib/linked_rails/enhancements/route_concerns.rb +0 -56
  177. data/lib/linked_rails/enhancements/singularable/controller.rb +0 -43
  178. data/lib/linked_rails/enhancements/singularable/model.rb +0 -47
  179. data/lib/linked_rails/enhancements/singularable/serializer.rb +0 -28
  180. data/lib/linked_rails/enhancements/tableable/model.rb +0 -28
  181. data/lib/linked_rails/enhancements/updatable/action.rb +0 -15
  182. data/lib/linked_rails/enhancements/updatable/routing.rb +0 -20
@@ -8,14 +8,14 @@ module LinkedRails
8
8
  include LinkedRails::Model
9
9
 
10
10
  attr_accessor :collection, :filter
11
- delegate :apply_scope, :association_base, :association_class, :default_page_size, :display,
11
+ delegate :apply_scope, :association_base, :association_class, :default_page_size, :display, :include_members,
12
12
  :parent, :policy, :total_page_count, :unfiltered_collection, :user_context, to: :collection
13
13
  delegate :count, to: :members
14
14
 
15
15
  alias id iri
16
16
 
17
- def root_relative_iri(opts = {})
18
- collection.unfiltered.root_relative_iri(iri_opts.merge(opts))
17
+ def root_relative_iri(**opts)
18
+ collection.unfiltered.root_relative_iri(**iri_opts.merge(opts))
19
19
  end
20
20
 
21
21
  def member_sequence
@@ -28,7 +28,7 @@ module LinkedRails
28
28
  end
29
29
 
30
30
  def members
31
- @members ||= raw_members
31
+ @members ||= include_members ? members_array : iris_from_members
32
32
  end
33
33
 
34
34
  def members_iri
@@ -42,9 +42,7 @@ module LinkedRails
42
42
  end
43
43
 
44
44
  def preview_includes
45
- return {member_sequence: {}} unless association_class.include_in_collection?
46
-
47
- {member_sequence: {members: association_class.preview_includes}}
45
+ include_members ? {member_sequence: :members} : %i[member_sequence]
48
46
  end
49
47
 
50
48
  def title
@@ -62,6 +60,39 @@ module LinkedRails
62
60
  @arel_table ||= association_class.arel_table
63
61
  end
64
62
 
63
+ def iris_from_members
64
+ iris_from_scope || iris_from_records
65
+ end
66
+
67
+ def iris_from_records
68
+ members_query.map(&:iri)
69
+ end
70
+
71
+ def iris_from_scope
72
+ return unless iris_from_scope?
73
+
74
+ association_class.try(:iris_from_scope, members_query)
75
+ end
76
+
77
+ def iris_from_scope?
78
+ members_query.is_a?(ActiveRecord::Relation) && !polymorphic_collection?
79
+ end
80
+
81
+ def members_array
82
+ members_query.to_a
83
+ end
84
+
85
+ def polymorphic_collection?
86
+ column = association_class.inheritance_column
87
+ polymorphic = association_class.columns_hash.include?(column)
88
+ return false unless polymorphic
89
+
90
+ return true if association_class.descends_from_active_record?
91
+
92
+ members_query.where_values_hash.include?(column) &&
93
+ members_query.where_values_hash[column] != association_class.to_s
94
+ end
95
+
65
96
  def prepare_members(scope)
66
97
  if scope.respond_to?(:preload) && association_class.try(:includes_for_serializer)
67
98
  scope = scope.preload(association_class.includes_for_serializer)
@@ -69,24 +100,20 @@ module LinkedRails
69
100
  scope
70
101
  end
71
102
 
72
- def raw_members
73
- @raw_members ||= members_query.to_a
74
- end
75
-
76
103
  class << self
77
104
  def iri
78
105
  [super, Vocab.as.CollectionPage]
79
106
  end
80
107
 
81
- def new(opts = {})
108
+ def new(**opts)
82
109
  type = opts.delete(:type)&.to_sym
83
110
  return super if type.nil?
84
111
 
85
112
  case type
86
113
  when :paginated
87
- LinkedRails.collection_paginated_view_class.new(opts)
114
+ collection_paginated_view_class.new(**opts)
88
115
  when :infinite
89
- LinkedRails.collection_infinite_view_class.new(opts)
116
+ collection_infinite_view_class.new(**opts)
90
117
  else
91
118
  raise ActionController::BadRequest, "'#{type}' is not a valid collection type"
92
119
  end
@@ -95,6 +122,16 @@ module LinkedRails
95
122
  def policy_class
96
123
  LinkedRails::Collection::ViewPolicy
97
124
  end
125
+
126
+ private
127
+
128
+ def collection_paginated_view_class
129
+ LinkedRails.collection_paginated_view_class
130
+ end
131
+
132
+ def collection_infinite_view_class
133
+ LinkedRails.collection_infinite_view_class
134
+ end
98
135
  end
99
136
  end
100
137
  end
@@ -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::Enhancements
19
- include LinkedRails::Model::Iri
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::Iri
22
- include LinkedRails::Collection::IriMapping
25
+ include LinkedRails::Collection::IRI
26
+ include LinkedRails::Collection::IRIMapping
23
27
  include LinkedRails::Collection::Sortable
24
28
 
25
- enhance LinkedRails::Enhancements::Actionable
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 association_base
60
- @association_base ||= apply_scope(sorted_association(filtered_association))
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 / (page_size || default_page_size).to_f).ceil if 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 = LinkedRails.collection_view_class.new({collection: self, type: type}.merge(opts))
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 default_display
171
- @default_display = @default_display.call(parent) if @default_display.respond_to?(:call)
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
- @default_display || association_class.try(:default_collection_display)
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 default_type
177
- @default_type || association_class.try(:default_collection_type) || :paginated
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 table_type
201
- return @table_type if @table_type
159
+ def permitted_attributes_from_filters(child)
160
+ return {} if @filter.empty?
202
161
 
203
- case display&.to_sym
204
- when :table
205
- :default
206
- when :settingsTable
207
- :settings
208
- end
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('association', 'association_class', 'association_scope', 'iri_template', 'parent')
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
@@ -8,7 +8,7 @@ module LinkedRails
8
8
  attr_writer :iri
9
9
  attr_accessor :description, :name, :text, :url
10
10
 
11
- def iri(_opts = {})
11
+ def iri(**_opts)
12
12
  @iri ||= RDF::Node.new
13
13
  end
14
14
 
@@ -6,7 +6,7 @@ module LinkedRails
6
6
  include LinkedRails::Model
7
7
 
8
8
  attr_accessor :parent
9
- attr_writer :url
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(URITemplate.new(parent.root_relative_iri.to_s), :EntryPoint)
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 url
34
- @url || parent.url
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 ||= klass_name.constantize.form_class
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
@@ -4,6 +4,7 @@ module LinkedRails
4
4
  class Form
5
5
  class Field
6
6
  class FileInput < Field
7
+ attr_accessor :max_size
7
8
  end
8
9
  end
9
10
  end
@@ -10,6 +10,8 @@ module LinkedRails
10
10
 
11
11
  attr_reader :path
12
12
 
13
+ def label_from_property; end
14
+
13
15
  def permission_required?
14
16
  false
15
17
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LinkedRails
4
- module Enhancements
5
- module Indexable
6
- module Model
4
+ class Form
5
+ class Field
6
+ class UrlInput < Field
7
7
  end
8
8
  end
9
9
  end
@@ -2,25 +2,27 @@
2
2
 
3
3
  module LinkedRails
4
4
  class Form
5
- class Field < LinkedRails::Resource
6
- attr_writer :datatype,
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
- attr_accessor :default_value,
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
- field_label = LinkedRails.translate(:field, :label, self, false)
105
- return field_label if field_label.present?
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]