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.
Files changed (173) 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 +71 -21
  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 +16 -21
  36. data/app/models/linked_rails/manifest.rb +8 -2
  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 +5 -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/serializers/linked_rails/actions/item_serializer.rb +5 -5
  51. data/app/serializers/linked_rails/actions/object_serializer.rb +9 -0
  52. data/app/serializers/linked_rails/collection/filter_field_serializer.rb +3 -2
  53. data/app/serializers/linked_rails/collection/filter_option_serializer.rb +1 -1
  54. data/app/serializers/linked_rails/collection/filter_serializer.rb +1 -1
  55. data/app/serializers/linked_rails/collection/sorting_serializer.rb +1 -1
  56. data/app/serializers/linked_rails/collection/view_serializer.rb +3 -3
  57. data/app/serializers/linked_rails/collection_serializer.rb +8 -7
  58. data/app/serializers/linked_rails/condition_serializer.rb +3 -3
  59. data/app/serializers/linked_rails/entry_point_serializer.rb +3 -3
  60. data/app/serializers/linked_rails/enum_value_serializer.rb +1 -0
  61. data/app/serializers/linked_rails/form/field/association_input_serializer.rb +1 -0
  62. data/app/serializers/linked_rails/form/field/file_input_serializer.rb +11 -0
  63. data/app/serializers/linked_rails/form/field_serializer.rb +3 -1
  64. data/app/serializers/linked_rails/form/group_serializer.rb +1 -1
  65. data/app/serializers/linked_rails/form/page_serializer.rb +1 -1
  66. data/app/serializers/linked_rails/menus/item_serializer.rb +3 -3
  67. data/app/serializers/linked_rails/menus/list_serializer.rb +1 -1
  68. data/app/serializers/linked_rails/ontology_serializer.rb +2 -2
  69. data/app/serializers/linked_rails/property_query_serializer.rb +7 -0
  70. data/app/serializers/linked_rails/sequence_serializer.rb +2 -5
  71. data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +1 -1
  72. data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +1 -1
  73. data/app/serializers/linked_rails/shacl/shape_serializer.rb +5 -5
  74. data/app/serializers/linked_rails/web_page_serializer.rb +3 -3
  75. data/app/serializers/linked_rails/web_site_serializer.rb +1 -1
  76. data/app/serializers/linked_rails/widget_serializer.rb +3 -3
  77. data/lib/generators/linked_rails/install/install_generator.rb +5 -8
  78. data/lib/generators/linked_rails/install/templates/README +2 -0
  79. data/lib/generators/linked_rails/install/templates/app_menu_list.rb +36 -7
  80. data/lib/generators/linked_rails/install/templates/application_menu_list.rb +40 -1
  81. data/lib/generators/linked_rails/install/templates/initializer.rb +1 -2
  82. data/lib/generators/linked_rails/install/templates/locales.yml +14 -0
  83. data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +1 -1
  84. data/lib/generators/linked_rails/install/templates/vocab.rb +1 -0
  85. data/lib/generators/linked_rails/install/templates/vocab.yml +2 -2
  86. data/lib/generators/linked_rails/model/model_generator.rb +0 -1
  87. data/lib/generators/linked_rails/model/templates/controller.rb.tt +5 -1
  88. data/lib/generators/linked_rails/model/templates/form.rb.tt +3 -0
  89. data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +15 -0
  90. data/lib/generators/linked_rails/model/templates/policy.rb.tt +13 -0
  91. data/lib/generators/linked_rails/model/templates/serializer.rb.tt +5 -1
  92. data/lib/linked_rails/active_response/controller/collections.rb +1 -1
  93. data/lib/linked_rails/active_response/controller/crud_defaults.rb +4 -4
  94. data/lib/linked_rails/active_response/controller/params.rb +10 -10
  95. data/lib/linked_rails/active_response/controller.rb +8 -18
  96. data/lib/linked_rails/active_response/responders/rdf.rb +19 -10
  97. data/lib/linked_rails/callable_variable.rb +1 -1
  98. data/lib/linked_rails/collection_params_parser.rb +93 -0
  99. data/lib/linked_rails/controller/actionable.rb +121 -0
  100. data/lib/linked_rails/controller/authorization.rb +6 -0
  101. data/lib/linked_rails/controller/default_actions/create.rb +52 -0
  102. data/lib/linked_rails/controller/default_actions/destroy.rb +42 -0
  103. data/lib/linked_rails/controller/default_actions/update.rb +43 -0
  104. data/lib/linked_rails/controller/delta.rb +78 -0
  105. data/lib/linked_rails/controller/error_handling.rb +10 -10
  106. data/lib/linked_rails/controller/rendering.rb +48 -0
  107. data/lib/linked_rails/controller.rb +24 -4
  108. data/lib/linked_rails/enhancements/creatable/controller.rb +1 -1
  109. data/lib/linked_rails/enhancements/destroyable/controller.rb +1 -1
  110. data/lib/linked_rails/enhancements/updatable/controller.rb +1 -1
  111. data/lib/linked_rails/enhancements.rb +0 -16
  112. data/lib/linked_rails/helpers/delta_helper.rb +26 -57
  113. data/lib/linked_rails/helpers/ontola_actions_helper.rb +2 -2
  114. data/lib/linked_rails/helpers/resource_helper.rb +4 -2
  115. data/lib/linked_rails/iri_mapper.rb +17 -39
  116. data/lib/linked_rails/middleware/error_handling.rb +51 -0
  117. data/lib/linked_rails/middleware/linked_data_params.rb +30 -151
  118. data/lib/linked_rails/model/actionable.rb +68 -0
  119. data/lib/linked_rails/model/collections.rb +201 -39
  120. data/lib/linked_rails/model/dirty.rb +7 -8
  121. data/lib/linked_rails/model/enhancements.rb +1 -6
  122. data/lib/linked_rails/model/filtering.rb +4 -6
  123. data/lib/linked_rails/model/indexable.rb +6 -16
  124. data/lib/linked_rails/model/iri.rb +28 -19
  125. data/lib/linked_rails/model/iri_mapping.rb +37 -8
  126. data/lib/linked_rails/model/menuable.rb +28 -0
  127. data/lib/linked_rails/model/serialization.rb +2 -15
  128. data/lib/linked_rails/model/singularable.rb +57 -0
  129. data/lib/linked_rails/model/sorting.rb +0 -5
  130. data/lib/linked_rails/model/tables.rb +26 -0
  131. data/lib/linked_rails/model.rb +17 -7
  132. data/lib/linked_rails/params_parser.rb +133 -55
  133. data/lib/linked_rails/policy/attribute_conditions.rb +2 -2
  134. data/lib/linked_rails/policy.rb +40 -46
  135. data/lib/linked_rails/railtie.rb +11 -0
  136. data/lib/linked_rails/rdf_error.rb +2 -2
  137. data/lib/linked_rails/renderers.rb +1 -0
  138. data/lib/linked_rails/routes.rb +38 -22
  139. data/lib/linked_rails/serializer/actionable.rb +27 -0
  140. data/lib/linked_rails/serializer/menuable.rb +31 -0
  141. data/lib/linked_rails/serializer/singularable.rb +26 -0
  142. data/lib/linked_rails/serializer.rb +28 -11
  143. data/lib/linked_rails/test_methods.rb +114 -0
  144. data/lib/linked_rails/translate.rb +31 -9
  145. data/lib/linked_rails/types/iri_type.rb +37 -0
  146. data/lib/linked_rails/uri_template.rb +30 -0
  147. data/lib/linked_rails/version.rb +1 -1
  148. data/lib/linked_rails/vocab.rb +9 -0
  149. data/lib/linked_rails.rb +30 -13
  150. data/lib/rails/welcome_controller.rb +3 -3
  151. data/lib/rdf/list.rb +9 -0
  152. data/lib/rdf/query_fix.rb +15 -0
  153. metadata +57 -33
  154. data/app/models/linked_rails/actions/default_actions/create.rb +0 -60
  155. data/app/models/linked_rails/actions/default_actions/destroy.rb +0 -45
  156. data/app/models/linked_rails/actions/default_actions/update.rb +0 -50
  157. data/app/models/linked_rails/actions/default_actions.rb +0 -17
  158. data/lib/generators/linked_rails/install/templates/application_action_list.rb +0 -3
  159. data/lib/generators/linked_rails/model/templates/action_list.rb.tt +0 -6
  160. data/lib/linked_rails/enhancements/actionable/model.rb +0 -71
  161. data/lib/linked_rails/enhancements/actionable/serializer.rb +0 -25
  162. data/lib/linked_rails/enhancements/creatable/action.rb +0 -15
  163. data/lib/linked_rails/enhancements/destroyable/action.rb +0 -15
  164. data/lib/linked_rails/enhancements/destroyable/routing.rb +0 -19
  165. data/lib/linked_rails/enhancements/menuable/model.rb +0 -36
  166. data/lib/linked_rails/enhancements/menuable/serializer.rb +0 -33
  167. data/lib/linked_rails/enhancements/route_concerns.rb +0 -56
  168. data/lib/linked_rails/enhancements/singularable/controller.rb +0 -43
  169. data/lib/linked_rails/enhancements/singularable/model.rb +0 -47
  170. data/lib/linked_rails/enhancements/singularable/serializer.rb +0 -28
  171. data/lib/linked_rails/enhancements/tableable/model.rb +0 -28
  172. data/lib/linked_rails/enhancements/updatable/action.rb +0 -15
  173. data/lib/linked_rails/enhancements/updatable/routing.rb +0 -20
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Actions
5
+ class ObjectsController < LinkedRails.controller_parent_class
6
+ active_response :show
7
+ end
8
+ end
9
+ end
@@ -11,7 +11,8 @@ module LinkedRails
11
11
  def show
12
12
  render json: authorized_resources
13
13
 
14
- print_timings
14
+ print_timings unless Rails.env.production?
15
+ send_timings if client
15
16
  end
16
17
 
17
18
  private
@@ -30,12 +31,16 @@ module LinkedRails
30
31
  @authorized_resources ||=
31
32
  params
32
33
  .require(:resources)
33
- .map { |param| param.permit(:include, :iri) }
34
+ .map { |param| resource_params(param) }
34
35
  .map(&method(:timed_authorized_resource))
35
36
  end
36
37
 
38
+ def client
39
+ nil
40
+ end
41
+
37
42
  def handle_resource_error(opts, error)
38
- log_resource_error(error)
43
+ log_resource_error(error, opts[:iri])
39
44
  status = error_status(error)
40
45
  body = error_body(status, error, opts[:iri]) if opts[:include].to_s == 'true'
41
46
 
@@ -50,7 +55,7 @@ module LinkedRails
50
55
  resource_body(error_resource(status, error, iri))
51
56
  end
52
57
 
53
- def log_resource_error(error)
58
+ def log_resource_error(error, _iri)
54
59
  return unless log_resource_error?(error)
55
60
 
56
61
  Rails.logger.error(error)
@@ -64,23 +69,25 @@ module LinkedRails
64
69
  def print_timings
65
70
  Rails.logger.debug(
66
71
  "\n CPU system user+system real inc status cache iri\n" \
67
- "#{timings.join("\n")}\n" \
72
+ "#{timing_lines.join("\n")}\n" \
68
73
  " User: #{current_user.class}(#{current_user.id})"
69
74
  )
70
75
  end
71
76
 
77
+ def send_timings
78
+ timings.each do |timing|
79
+ client.send_json(timing_json(timing))
80
+ end
81
+ end
82
+
72
83
  def require_doorkeeper_token?
73
84
  false
74
85
  end
75
86
 
76
- def resource_body(resource)
77
- return if resource.nil?
78
-
79
- serializer_options = RDF::Serializers::Renderers.transform_opts(
80
- {include: resource&.try(:preview_includes)},
81
- serializer_params
82
- )
83
- RDF::Serializers.serializer_for(resource).new(resource, serializer_options).send(:render_hndjson)
87
+ def resource_params(param)
88
+ params = param.permit(:include, :iri)
89
+ params[:iri] = URI(params[:iri])
90
+ params
84
91
  end
85
92
 
86
93
  def resource_response_body(iri, rack_body, status)
@@ -109,7 +116,7 @@ module LinkedRails
109
116
  fullpath = iri.query.blank? ? iri.path : "#{iri.path}?#{iri.query}"
110
117
 
111
118
  request.env.slice(*REQUEST_HEADERS).merge(
112
- 'HTTP_ACCEPT' => 'application/hex+x-ndjson',
119
+ 'HTTP_ACCEPT' => 'application/empathy+json',
113
120
  'HTTP_OPERATOR_ARG_GRAPH' => 'true',
114
121
  'ORIGINAL_FULLPATH' => fullpath
115
122
  )
@@ -134,16 +141,54 @@ module LinkedRails
134
141
 
135
142
  def term_from_vocab(iri)
136
143
  vocab = Vocab.for(iri)
137
- tag = iri.split(vocab.to_s).last
144
+ tag = iri.to_s.split(vocab.to_s).last
138
145
  vocab[tag]
139
146
  rescue NoMethodError
140
147
  nil
141
148
  end
142
149
 
150
+ def timing_json(timing) # rubocop:disable Metrics/MethodLength
151
+ route = Rails.application.routes.recognize_path(timing[:resource].to_s)
152
+
153
+ {
154
+ type: 'web',
155
+ timings: {
156
+ total_duration: timing[:time].total
157
+ },
158
+ default_labels: {
159
+ action: route[:action] || 'show',
160
+ controller: route[:controller] || 'subresource',
161
+ status: timing[:status],
162
+ include: timing[:include]
163
+ }
164
+ }
165
+ end
166
+
167
+ def timing_lines
168
+ timings.map do |timing|
169
+ include = timing[:include].to_s.ljust(5)
170
+ "#{timing[:time].to_s[0..-2]} - #{include} #{timing[:status]} #{timing[:cache]} #{timing[:resource]}"
171
+ end
172
+ end
173
+
174
+ def ontology_class(iri)
175
+ klass = LinkedRails.linked_models.detect do |model|
176
+ (model.iri.is_a?(Array) ? model.iri : [model.iri]).include?(iri)
177
+ end
178
+ LinkedRails.ontology_class_class.new(iri: iri, klass: klass)
179
+ end
180
+
181
+ def ontology_property(iri)
182
+ LinkedRails.ontology_property_class.new(iri: iri)
183
+ end
184
+
143
185
  def ontology_term_response(iri, term, include)
186
+ capital = term.relativize(term.vocab).to_s[0] =~ /[A-Z]/
187
+ resource = capital ? ontology_class(term) : ontology_property(term)
188
+
144
189
  resource_response(
145
190
  iri,
146
- body: include ? resource_body(LinkedRails.ontology_property_class.new(iri: term)) : nil,
191
+ body: include ? resource_body(resource) : nil,
147
192
  cache: :public,
148
193
  language: I18n.locale,
149
194
  status: 200
@@ -161,6 +206,8 @@ module LinkedRails
161
206
  language: response_language(headers),
162
207
  status: status
163
208
  )
209
+ rescue URI::InvalidURIError, ActionController::BadRequest
210
+ resource_response(iri)
164
211
  end
165
212
 
166
213
  def response_language(headers)
@@ -181,15 +228,18 @@ module LinkedRails
181
228
  def timed_authorized_resource(resource)
182
229
  res = nil
183
230
  time = Benchmark.measure { res = authorized_resource(resource) }
184
- unless Rails.env.production?
185
- include = resource[:include].to_s.ljust(5)
186
- timings << "#{time.to_s[0..-2]} - #{include} #{res[:status]} #{res[:cache]} #{resource[:iri]}"
187
- end
231
+ timings << {
232
+ time: time,
233
+ include: resource[:include],
234
+ status: res[:status],
235
+ cache: res[:cache],
236
+ resource: resource[:iri]
237
+ }
188
238
  res
189
239
  end
190
240
 
191
241
  def wrong_host?(iri)
192
- !iri.starts_with?(LinkedRails.iri)
242
+ !iri.to_s.starts_with?(LinkedRails.iri)
193
243
  end
194
244
  end
195
245
  end
@@ -3,47 +3,5 @@
3
3
  module LinkedRails
4
4
  class EnumValuesController < LinkedRails.controller_parent_class
5
5
  active_response :index
6
-
7
- private
8
-
9
- def enum_options!
10
- serializer_class!.enum_options(params[:attribute]) || raise(ActiveRecord::RecordNotFound)
11
- end
12
-
13
- def requested_resource
14
- return super unless action_name == 'index'
15
-
16
- @requested_resource ||= LinkedRails::Sequence.new(
17
- enum_options!.values,
18
- id: index_iri,
19
- scope: LinkedRails::EnumValuePolicy::Scope
20
- )
21
- end
22
-
23
- def model_class
24
- @model_class ||= self.class.linked_models.detect do |klass|
25
- klass.to_s == ([params[:module]].compact + [params[:klass]&.singularize]).join('/').classify
26
- end
27
- end
28
-
29
- def model_class!
30
- model_class || raise(ActiveRecord::RecordNotFound)
31
- end
32
-
33
- def serializer_class
34
- @serializer_class ||= RDF::Serializers.serializer_for(model_class!)
35
- end
36
-
37
- def serializer_class!
38
- serializer_class || raise(ActiveRecord::RecordNotFound)
39
- end
40
-
41
- class << self
42
- def linked_models
43
- @linked_models ||= ObjectSpace.each_object(Class).select do |c|
44
- c.included_modules.include?(LinkedRails::Model)
45
- end
46
- end
47
- end
48
6
  end
49
7
  end
@@ -7,15 +7,23 @@ module LinkedRails
7
7
  class Item # rubocop:disable Metrics/ClassLength
8
8
  include ActiveModel::Model
9
9
  include LinkedRails::Model
10
- enhance LinkedRails::Enhancements::Singularable
11
10
 
12
- attr_accessor :list, :policy_arguments, :submit_label
11
+ attr_accessor :inherit, :list, :one_click, :policy_arguments, :submit_label, :target_path, :target_query
13
12
  attr_writer :parent, :resource, :root_relative_iri, :user_context, :object,
14
13
  :target
15
14
  delegate :user_context, to: :list, allow_nil: true
16
-
17
- %i[description result type policy label image url include_object include_paths collection condition form completed
18
- tag http_method favorite path policy_resource predicate resource].each do |method|
15
+ collection_options(
16
+ association_base: lambda {
17
+ action_list = association_class.get_action_list(parent, user_context)
18
+
19
+ action_list.actions
20
+ },
21
+ display: :grid,
22
+ title: -> { I18n.t('actions.plural') }
23
+ )
24
+
25
+ %i[condition description result type policy label image target_url collection form
26
+ tag http_method favorite action_path policy_resource predicate resource].each do |method|
19
27
  attr_writer method
20
28
  define_method method do
21
29
  var = instance_variable_get(:"@#{method}")
@@ -28,10 +36,10 @@ module LinkedRails
28
36
 
29
37
  def action_status
30
38
  @action_status ||=
31
- if completed
32
- Vocab.schema.CompletedActionStatus
33
- elsif policy_valid?
39
+ if policy_valid?
34
40
  Vocab.schema.PotentialActionStatus
41
+ elsif policy_status
42
+ policy_status
35
43
  elsif policy_expired?
36
44
  Vocab.ontola[:ExpiredActionStatus]
37
45
  else
@@ -39,48 +47,29 @@ module LinkedRails
39
47
  end
40
48
  end
41
49
 
42
- def as_json(_opts = {})
50
+ def as_json(**_opts)
43
51
  {}
44
52
  end
45
53
 
46
54
  def available?
47
- return false unless action_status == Vocab.schema.PotentialActionStatus
48
-
49
55
  @condition.nil? || condition
50
56
  end
51
57
 
52
- def built_associations
53
- included_object
54
- .class
55
- .try(:reflect_on_all_associations)
56
- &.select { |association| included_object.association(association.name).loaded? }
57
- &.map(&:name)
58
- end
59
-
60
58
  def error
61
59
  policy_message ||
62
60
  I18n.t("actions.status.#{action_status.to_s.split('#').last}", default: nil)
63
61
  end
64
62
 
65
- def form_resource_includes # rubocop:disable Metrics/CyclomaticComplexity
66
- return {} if included_object.nil?
67
- return include_paths || {} if iri.anonymous?
68
-
69
- includes = included_object.class.try(:preview_includes)&.presence || []
70
-
71
- (includes.is_a?(Hash) ? [includes] : includes) + (built_associations || [])
72
- end
73
-
74
- def included_object
75
- object if include_object || object&.iri&.anonymous?
76
- end
77
-
78
63
  def object
79
64
  @object = list.instance_exec(&@object) if @object.respond_to?(:call)
80
65
 
81
66
  @object || resource
82
67
  end
83
68
 
69
+ def object_iri
70
+ object&.iri&.anonymous? ? anonymous_object_iri : object&.iri
71
+ end
72
+
84
73
  def parent
85
74
  return @parent if instance_variable_defined?(:@parent)
86
75
 
@@ -92,10 +81,10 @@ module LinkedRails
92
81
  end
93
82
 
94
83
  def policy_message
95
- resource_policy.try(:message) if action_status == Vocab.ontola[:DisabledActionStatus]
84
+ resource_policy.try(:message) unless policy_valid?
96
85
  end
97
86
 
98
- def root_relative_iri(_opts = {})
87
+ def root_relative_iri(**_opts)
99
88
  value = root_relative_iri_from_var
100
89
  value = RDF::URI(value) unless value.blank? || value.is_a?(RDF::URI)
101
90
  return @root_relative_iri = value if value
@@ -109,24 +98,30 @@ module LinkedRails
109
98
  RDF::URI(value)
110
99
  end
111
100
 
112
- def preview_includes
113
- [:target, included_object: form_resource_includes]
114
- end
115
-
116
101
  def singular_resource?
117
102
  resource.try(:singular_resource?)
118
103
  end
119
104
 
105
+ def policy_status
106
+ resource_policy.try(:action_status)
107
+ end
108
+
120
109
  def iri_opts
121
- resource&.iri_opts || {}
110
+ return {} if resource.blank?
111
+
112
+ resource.try(:singular_resource?) ? resource.singular_iri_opts : resource.iri_opts
122
113
  end
123
114
 
124
115
  def iri_template
125
- path_suffix = path.blank? ? "/actions/#{tag}" : "/#{path}"
116
+ path_suffix = "/#{action_path || tag}"
126
117
 
127
- return @iri_template ||= URITemplate.new(path_suffix) if resource.blank?
118
+ return @iri_template ||= LinkedRails::URITemplate.new(path_suffix) if resource.blank?
128
119
 
129
- @iri_template ||= iri_template_expand_path(resource.send(:iri_template), path_suffix)
120
+ base_template = resource.send(resource.try(:singular_resource?) ? :singular_iri_template : :iri_template)
121
+ @iri_template ||= iri_template_expand_path(
122
+ base_template.to_s.sub('display,', '').sub('sort%5B%5D*,', ''),
123
+ path_suffix
124
+ )
130
125
  end
131
126
 
132
127
  def rdf_type
@@ -143,6 +138,12 @@ module LinkedRails
143
138
 
144
139
  private
145
140
 
141
+ def anonymous_object_iri
142
+ object_iri = iri.dup
143
+ object_iri.path += '/action_object'
144
+ object_iri
145
+ end
146
+
146
147
  def description_fallback
147
148
  LinkedRails.translate(:action, :description, self, false)
148
149
  end
@@ -156,7 +157,7 @@ module LinkedRails
156
157
  end
157
158
 
158
159
  def policy_resource_fallback
159
- resource
160
+ object
160
161
  end
161
162
 
162
163
  def policy_valid?
@@ -184,6 +185,13 @@ module LinkedRails
184
185
  @root_relative_iri
185
186
  end
186
187
 
188
+ def target_url_fallback # rubocop:disable Metrics/AbcSize
189
+ base = (resource.try(:singular_resource?) ? resource.singular_iri : resource.iri).dup
190
+ base.path = "#{base.path}/#{target_path}" if target_path.present?
191
+ base.query = Rack::Utils.parse_nested_query(base.query).merge(target_query).to_param if target_query.present?
192
+ base
193
+ end
194
+
187
195
  def type_fallback
188
196
  Vocab.schema.UpdateAction
189
197
  end
@@ -202,25 +210,26 @@ module LinkedRails
202
210
  )
203
211
  end
204
212
 
213
+ def get_action_list(parent, user_context)
214
+ return parent.action_list(user_context) if parent.respond_to?(:action_list)
215
+
216
+ app_action_list(user_context)
217
+ end
218
+
205
219
  def requested_index_resource(params, user_context)
206
- parent = parent_from_params(params, user_context)
207
- action_list = parent ? parent.action_list(user_context) : app_action_list(user_context)
208
-
209
- LinkedRails.collection_class.new(
210
- association_base: action_list.actions,
211
- association_class: ::Actions::Item,
212
- default_display: :grid,
213
- default_title: I18n.t('actions.plural'),
214
- parent: parent,
215
- title: params[:title]
220
+ parent = parent_from_params!(params, user_context) if params.key?(:parent_iri)
221
+
222
+ default_collection_option(:collection_class).collection_or_view(
223
+ default_collection_options.merge(parent: parent),
224
+ index_collection_params(params, user_context)
216
225
  )
217
226
  end
218
227
 
219
228
  def requested_single_resource(params, user_context)
220
229
  return nil if params[:id].blank?
221
230
 
222
- parent = parent_from_params(params, user_context)
223
- action_list = parent ? parent.action_list(user_context) : app_action_list(user_context)
231
+ parent = parent_from_params!(params, user_context) if params.key?(:parent_iri)
232
+ action_list = get_action_list(parent, user_context)
224
233
 
225
234
  action_list&.action(params[:id].to_sym)
226
235
  end
@@ -7,14 +7,12 @@ module LinkedRails
7
7
  class List
8
8
  include ActiveModel::Model
9
9
  include LinkedRails::Model
10
- include DefaultActions
11
- extend LinkedRails::Enhanceable
12
10
 
13
11
  attr_accessor :resource, :user_context
14
12
  class_attribute :_defined_actions, instance_reader: false, instance_writer: false
15
13
 
16
14
  def actions
17
- @actions ||= defined_actions.map { |tag, opts| action_item(tag, opts.dup) }
15
+ @actions ||= defined_actions.map { |tag, opts| action_item(tag, opts.dup) }.select(&:available?)
18
16
  end
19
17
 
20
18
  def action(tag)
@@ -34,9 +32,9 @@ module LinkedRails
34
32
  private
35
33
 
36
34
  def action_item(tag, options)
37
- options[:tag] ||= options[:action_tag] || tag
35
+ options[:tag] ||= tag
38
36
  options[:list] ||= self
39
- LinkedRails.actions_item_class.new(options.except(:action_tag))
37
+ LinkedRails.actions_item_class.new(options.except(:action_name))
40
38
  end
41
39
 
42
40
  def association
@@ -52,12 +50,6 @@ module LinkedRails
52
50
  end
53
51
 
54
52
  class << self
55
- def actionable_class
56
- @actionable_class ||=
57
- name.gsub('ActionList', '').safe_constantize ||
58
- name.demodulize.gsub('ActionList', '').safe_constantize
59
- end
60
-
61
53
  def collection_actions
62
54
  defined_actions[:collection]
63
55
  end
@@ -77,26 +69,11 @@ module LinkedRails
77
69
 
78
70
  private
79
71
 
80
- def has_collection_action(action, opts = {}) # rubocop:disable Naming/PredicateName
81
- opts[:http_method] ||= 'POST'
82
- defined_actions[:collection][action] = opts
83
- end
84
-
85
- def has_resource_action(action, opts = {}) # rubocop:disable Naming/PredicateName
86
- opts[:http_method] ||= 'POST'
87
- defined_actions[:resource][action] = opts
88
- end
89
-
90
- def has_singular_action(action, opts = {}) # rubocop:disable Naming/PredicateName
91
- opts[:http_method] ||= 'POST'
92
- defined_actions[:singular][action] = opts
93
- end
94
-
95
72
  def initial_defined_actions(clone_from = {})
96
73
  {
97
- collection: clone_from[:collection].dup || {},
98
- resource: clone_from[:resource].dup || {},
99
- singular: clone_from[:singular].dup || {}
74
+ collection: clone_from[:collection].dup&.select { |_, value| value[:inherit] != false } || {},
75
+ resource: clone_from[:resource].dup&.select { |_, value| value[:inherit] != false } || {},
76
+ singular: clone_from[:singular].dup&.select { |_, value| value[:inherit] != false } || {}
100
77
  }
101
78
  end
102
79
 
@@ -106,8 +83,6 @@ module LinkedRails
106
83
  self._defined_actions = initial_defined_actions(superclass.try(:_defined_actions) || {})
107
84
  end
108
85
  end
109
-
110
- enhanceable :actionable_class, :Action
111
86
  end
112
87
  end
113
88
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pundit'
4
+
5
+ module LinkedRails
6
+ module Actions
7
+ class Object
8
+ include ActiveModel::Model
9
+ include LinkedRails::Model
10
+
11
+ attr_accessor :action
12
+ alias parent action
13
+ delegate :object, to: :action
14
+
15
+ def iri
16
+ action.object_iri
17
+ end
18
+
19
+ class << self
20
+ def requested_resource(opts, user_context)
21
+ return super unless opts[:iri].include?('?')
22
+
23
+ parent_iri_with_query = [opts[:params][:parent_iri], opts[:iri].split('?').last].compact.join('?')
24
+
25
+ super(opts.merge(params: opts[:params].merge(parent_iri: parent_iri_with_query)), user_context)
26
+ end
27
+
28
+ def requested_single_resource(params, user_context)
29
+ return unless params.key?(:parent_iri)
30
+
31
+ parent = parent_from_params!(params, user_context)
32
+
33
+ new(action: parent) if parent.object.anonymous_iri?
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class Collection
5
+ module Configuration
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ private
10
+
11
+ def define_default_option_method(option)
12
+ attr_accessor "default_#{option}"
13
+ end
14
+
15
+ def define_getter_option_method(option)
16
+ attr_writer option
17
+
18
+ define_method(option) do
19
+ resolve_collection_option(option)
20
+ end
21
+ end
22
+ end
23
+
24
+ included do
25
+ attr_accessor :iri_template
26
+
27
+ LinkedRails::Model::Collections::COLLECTION_CUSTOMIZABLE_OPTIONS.each_key do |option|
28
+ define_default_option_method(option)
29
+ end
30
+ LinkedRails::Model::Collections::COLLECTION_OPTIONS.each_key do |option|
31
+ define_getter_option_method(option)
32
+ end
33
+
34
+ def display
35
+ resolve_collection_option(:display)&.to_sym
36
+ end
37
+
38
+ def type
39
+ resolve_collection_option(:type)&.to_sym
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def resolve_collection_option(option)
46
+ var_name = :"@#{option}"
47
+ default_method_name = "default_#{option}"
48
+
49
+ var = instance_variable_defined?(var_name) ? instance_variable_get(var_name) : try(default_method_name)
50
+
51
+ var.respond_to?(:call) ? instance_exec(&var) : var
52
+ end
53
+ end
54
+ end
55
+ end
@@ -8,7 +8,7 @@ module LinkedRails
8
8
 
9
9
  attr_accessor :default_filter, :key, :value, :collection
10
10
 
11
- def iri(_opts = {})
11
+ def iri(**_opts)
12
12
  self
13
13
  end
14
14
  end
@@ -9,11 +9,12 @@ module LinkedRails
9
9
  include LinkedRails::CallableVariable
10
10
 
11
11
  attr_accessor :key, :klass, :collection
12
- attr_writer :options_array, :options_in
12
+ attr_writer :options_array, :options_in, :visible
13
13
  callable_variable(:options_array)
14
14
  callable_variable(:options_in)
15
+ callable_variable(:visible)
15
16
 
16
- def iri(_opts = {})
17
+ def iri(**_opts)
17
18
  self
18
19
  end
19
20
 
@@ -25,6 +26,22 @@ module LinkedRails
25
26
  attrs = option.is_a?(Hash) ? option : {value: option}
26
27
  Collection::FilterOption.new(attrs.merge(collection: collection, key: key))
27
28
  end
29
+
30
+ def visible?
31
+ has_options? && condition_valid?
32
+ end
33
+
34
+ private
35
+
36
+ def condition_valid?
37
+ return true if visible.nil?
38
+
39
+ visible
40
+ end
41
+
42
+ def has_options?
43
+ !!(options_in || options_array)
44
+ end
28
45
  end
29
46
  end
30
47
  end
@@ -9,7 +9,7 @@ module LinkedRails
9
9
 
10
10
  attr_accessor :collection, :count, :value, :key
11
11
 
12
- def iri(_opts = {})
12
+ def iri(**_opts)
13
13
  self
14
14
  end
15
15
  end