linked_rails 0.0.1

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 (207) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +65 -0
  4. data/Rakefile +34 -0
  5. data/app/controllers/linked_rails/actions/items_controller.rb +9 -0
  6. data/app/controllers/linked_rails/bulk_controller.rb +195 -0
  7. data/app/controllers/linked_rails/current_user_controller.rb +13 -0
  8. data/app/controllers/linked_rails/enum_values_controller.rb +49 -0
  9. data/app/controllers/linked_rails/forms_controller.rb +13 -0
  10. data/app/controllers/linked_rails/manifests_controller.rb +21 -0
  11. data/app/controllers/linked_rails/menus/items_controller.rb +9 -0
  12. data/app/controllers/linked_rails/menus/lists_controller.rb +9 -0
  13. data/app/controllers/linked_rails/not_found_controller.rb +15 -0
  14. data/app/controllers/linked_rails/ontologies_controller.rb +7 -0
  15. data/app/models/linked_rails/actions/default_actions/create.rb +60 -0
  16. data/app/models/linked_rails/actions/default_actions/destroy.rb +45 -0
  17. data/app/models/linked_rails/actions/default_actions/update.rb +50 -0
  18. data/app/models/linked_rails/actions/default_actions.rb +17 -0
  19. data/app/models/linked_rails/actions/item.rb +234 -0
  20. data/app/models/linked_rails/actions/list.rb +113 -0
  21. data/app/models/linked_rails/collection/filter.rb +16 -0
  22. data/app/models/linked_rails/collection/filter_field.rb +30 -0
  23. data/app/models/linked_rails/collection/filter_option.rb +17 -0
  24. data/app/models/linked_rails/collection/filterable.rb +92 -0
  25. data/app/models/linked_rails/collection/infinite_view.rb +98 -0
  26. data/app/models/linked_rails/collection/iri.rb +74 -0
  27. data/app/models/linked_rails/collection/iri_mapping.rb +33 -0
  28. data/app/models/linked_rails/collection/paginated_view.rb +41 -0
  29. data/app/models/linked_rails/collection/sortable.rb +60 -0
  30. data/app/models/linked_rails/collection/sorting.rb +72 -0
  31. data/app/models/linked_rails/collection/view.rb +101 -0
  32. data/app/models/linked_rails/collection.rb +220 -0
  33. data/app/models/linked_rails/condition.rb +7 -0
  34. data/app/models/linked_rails/creative_work.rb +21 -0
  35. data/app/models/linked_rails/current_user.rb +28 -0
  36. data/app/models/linked_rails/entry_point.rb +53 -0
  37. data/app/models/linked_rails/enum_value.rb +33 -0
  38. data/app/models/linked_rails/form/field/association_input.rb +23 -0
  39. data/app/models/linked_rails/form/field/checkbox_group.rb +10 -0
  40. data/app/models/linked_rails/form/field/checkbox_input.rb +10 -0
  41. data/app/models/linked_rails/form/field/color_input.rb +17 -0
  42. data/app/models/linked_rails/form/field/date_input.rb +10 -0
  43. data/app/models/linked_rails/form/field/date_time_input.rb +10 -0
  44. data/app/models/linked_rails/form/field/email_input.rb +10 -0
  45. data/app/models/linked_rails/form/field/file_input.rb +10 -0
  46. data/app/models/linked_rails/form/field/location_input.rb +11 -0
  47. data/app/models/linked_rails/form/field/markdown_input.rb +10 -0
  48. data/app/models/linked_rails/form/field/number_input.rb +10 -0
  49. data/app/models/linked_rails/form/field/password_input.rb +10 -0
  50. data/app/models/linked_rails/form/field/postal_range_input.rb +10 -0
  51. data/app/models/linked_rails/form/field/radio_group.rb +10 -0
  52. data/app/models/linked_rails/form/field/resource_field.rb +23 -0
  53. data/app/models/linked_rails/form/field/select_input.rb +11 -0
  54. data/app/models/linked_rails/form/field/slider_input.rb +10 -0
  55. data/app/models/linked_rails/form/field/text_area_input.rb +10 -0
  56. data/app/models/linked_rails/form/field/text_input.rb +10 -0
  57. data/app/models/linked_rails/form/field/toggle_button_group.rb +10 -0
  58. data/app/models/linked_rails/form/field.rb +117 -0
  59. data/app/models/linked_rails/form/field_factory.rb +219 -0
  60. data/app/models/linked_rails/form/group.rb +39 -0
  61. data/app/models/linked_rails/form/page.rb +31 -0
  62. data/app/models/linked_rails/form.rb +156 -0
  63. data/app/models/linked_rails/manifest.rb +102 -0
  64. data/app/models/linked_rails/media_object.rb +31 -0
  65. data/app/models/linked_rails/menus/item.rb +92 -0
  66. data/app/models/linked_rails/menus/list.rb +138 -0
  67. data/app/models/linked_rails/ontology/base.rb +50 -0
  68. data/app/models/linked_rails/ontology/class.rb +43 -0
  69. data/app/models/linked_rails/ontology/property.rb +19 -0
  70. data/app/models/linked_rails/ontology.rb +34 -0
  71. data/app/models/linked_rails/property_query.rb +11 -0
  72. data/app/models/linked_rails/resource.rb +17 -0
  73. data/app/models/linked_rails/sequence.rb +64 -0
  74. data/app/models/linked_rails/shacl/node_shape.rb +21 -0
  75. data/app/models/linked_rails/shacl/property_shape.rb +53 -0
  76. data/app/models/linked_rails/shacl/shape.rb +33 -0
  77. data/app/models/linked_rails/web_page.rb +22 -0
  78. data/app/models/linked_rails/web_site.rb +17 -0
  79. data/app/models/linked_rails/widget.rb +55 -0
  80. data/app/policies/linked_rails/actions/item_policy.rb +11 -0
  81. data/app/policies/linked_rails/actions/list_policy.rb +11 -0
  82. data/app/policies/linked_rails/collection/view_policy.rb +13 -0
  83. data/app/policies/linked_rails/collection_policy.rb +41 -0
  84. data/app/policies/linked_rails/enum_value_policy.rb +32 -0
  85. data/app/policies/linked_rails/menus/item_policy.rb +11 -0
  86. data/app/policies/linked_rails/menus/list_policy.rb +11 -0
  87. data/app/policies/linked_rails/sequence_policy.rb +9 -0
  88. data/app/serializers/linked_rails/actions/item_serializer.rb +28 -0
  89. data/app/serializers/linked_rails/collection/filter_field_serializer.rb +12 -0
  90. data/app/serializers/linked_rails/collection/filter_option_serializer.rb +12 -0
  91. data/app/serializers/linked_rails/collection/filter_serializer.rb +13 -0
  92. data/app/serializers/linked_rails/collection/sorting_serializer.rb +13 -0
  93. data/app/serializers/linked_rails/collection/view_serializer.rb +22 -0
  94. data/app/serializers/linked_rails/collection_serializer.rb +44 -0
  95. data/app/serializers/linked_rails/condition_serializer.rb +9 -0
  96. data/app/serializers/linked_rails/creative_work_serializer.rb +10 -0
  97. data/app/serializers/linked_rails/current_user_serializer.rb +7 -0
  98. data/app/serializers/linked_rails/entry_point_serializer.rb +20 -0
  99. data/app/serializers/linked_rails/enum_value_serializer.rb +12 -0
  100. data/app/serializers/linked_rails/form/field/association_input_serializer.rb +13 -0
  101. data/app/serializers/linked_rails/form/field/resource_field_serializer.rb +11 -0
  102. data/app/serializers/linked_rails/form/field/select_input_serializer.rb +11 -0
  103. data/app/serializers/linked_rails/form/field_serializer.rb +39 -0
  104. data/app/serializers/linked_rails/form/group_serializer.rb +14 -0
  105. data/app/serializers/linked_rails/form/page_serializer.rb +13 -0
  106. data/app/serializers/linked_rails/form_serializer.rb +9 -0
  107. data/app/serializers/linked_rails/media_object_serializer.rb +17 -0
  108. data/app/serializers/linked_rails/menus/item_serializer.rb +35 -0
  109. data/app/serializers/linked_rails/menus/list_serializer.rb +13 -0
  110. data/app/serializers/linked_rails/ontology/class_serializer.rb +19 -0
  111. data/app/serializers/linked_rails/ontology/property_serializer.rb +16 -0
  112. data/app/serializers/linked_rails/ontology_serializer.rb +8 -0
  113. data/app/serializers/linked_rails/rdf_error_serializer.rb +8 -0
  114. data/app/serializers/linked_rails/sequence_serializer.rb +14 -0
  115. data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +12 -0
  116. data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +38 -0
  117. data/app/serializers/linked_rails/shacl/shape_serializer.rb +25 -0
  118. data/app/serializers/linked_rails/web_page_serializer.rb +10 -0
  119. data/app/serializers/linked_rails/web_site_serializer.rb +11 -0
  120. data/app/serializers/linked_rails/widget_serializer.rb +15 -0
  121. data/config/initializers/inflections.rb +5 -0
  122. data/lib/generators/linked_rails/install/install_generator.rb +65 -0
  123. data/lib/generators/linked_rails/install/templates/app_menu_list.rb +41 -0
  124. data/lib/generators/linked_rails/install/templates/application_action_list.rb +3 -0
  125. data/lib/generators/linked_rails/install/templates/application_form.rb +3 -0
  126. data/lib/generators/linked_rails/install/templates/application_menu_list.rb +3 -0
  127. data/lib/generators/linked_rails/install/templates/application_policy.rb +18 -0
  128. data/lib/generators/linked_rails/install/templates/application_serializer.rb +5 -0
  129. data/lib/generators/linked_rails/install/templates/initializer.rb +9 -0
  130. data/lib/generators/linked_rails/install/templates/locales.yml +12 -0
  131. data/lib/generators/linked_rails/install/templates/rdf_responder.rb +5 -0
  132. data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +5 -0
  133. data/lib/generators/linked_rails/install/templates/vocab.rb +5 -0
  134. data/lib/generators/linked_rails/install/templates/vocab.yml +26 -0
  135. data/lib/generators/linked_rails/model/model_generator.rb +58 -0
  136. data/lib/generators/linked_rails/model/templates/action_list.rb.tt +6 -0
  137. data/lib/generators/linked_rails/model/templates/controller.rb.tt +7 -0
  138. data/lib/generators/linked_rails/model/templates/create_table_migration.rb.tt +24 -0
  139. data/lib/generators/linked_rails/model/templates/form.rb.tt +6 -0
  140. data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +6 -0
  141. data/lib/generators/linked_rails/model/templates/model.rb.tt +15 -0
  142. data/lib/generators/linked_rails/model/templates/module.rb.tt +7 -0
  143. data/lib/generators/linked_rails/model/templates/policy.rb.tt +6 -0
  144. data/lib/generators/linked_rails/model/templates/serializer.rb.tt +9 -0
  145. data/lib/linked_rails/active_response/controller/collections.rb +43 -0
  146. data/lib/linked_rails/active_response/controller/crud_defaults.rb +92 -0
  147. data/lib/linked_rails/active_response/controller/params.rb +51 -0
  148. data/lib/linked_rails/active_response/controller.rb +37 -0
  149. data/lib/linked_rails/active_response/responders/rdf.rb +158 -0
  150. data/lib/linked_rails/cache.rb +35 -0
  151. data/lib/linked_rails/callable_variable.rb +25 -0
  152. data/lib/linked_rails/constraints/whitelist.rb +36 -0
  153. data/lib/linked_rails/controller/authorization.rb +15 -0
  154. data/lib/linked_rails/controller/error_handling.rb +76 -0
  155. data/lib/linked_rails/controller.rb +43 -0
  156. data/lib/linked_rails/engine.rb +7 -0
  157. data/lib/linked_rails/enhanceable.rb +21 -0
  158. data/lib/linked_rails/enhancements/actionable/model.rb +71 -0
  159. data/lib/linked_rails/enhancements/actionable/serializer.rb +25 -0
  160. data/lib/linked_rails/enhancements/creatable/action.rb +15 -0
  161. data/lib/linked_rails/enhancements/creatable/controller.rb +15 -0
  162. data/lib/linked_rails/enhancements/destroyable/action.rb +15 -0
  163. data/lib/linked_rails/enhancements/destroyable/controller.rb +15 -0
  164. data/lib/linked_rails/enhancements/destroyable/routing.rb +19 -0
  165. data/lib/linked_rails/enhancements/indexable/model.rb +10 -0
  166. data/lib/linked_rails/enhancements/menuable/model.rb +36 -0
  167. data/lib/linked_rails/enhancements/menuable/serializer.rb +33 -0
  168. data/lib/linked_rails/enhancements/route_concerns.rb +56 -0
  169. data/lib/linked_rails/enhancements/singularable/controller.rb +43 -0
  170. data/lib/linked_rails/enhancements/singularable/model.rb +47 -0
  171. data/lib/linked_rails/enhancements/singularable/serializer.rb +28 -0
  172. data/lib/linked_rails/enhancements/tableable/model.rb +28 -0
  173. data/lib/linked_rails/enhancements/updatable/action.rb +15 -0
  174. data/lib/linked_rails/enhancements/updatable/controller.rb +15 -0
  175. data/lib/linked_rails/enhancements/updatable/routing.rb +20 -0
  176. data/lib/linked_rails/enhancements/updatable/serializer.rb +17 -0
  177. data/lib/linked_rails/enhancements.rb +22 -0
  178. data/lib/linked_rails/helpers/delta_helper.rb +86 -0
  179. data/lib/linked_rails/helpers/ontola_actions_helper.rb +32 -0
  180. data/lib/linked_rails/helpers/resource_helper.rb +70 -0
  181. data/lib/linked_rails/iri_mapper.rb +125 -0
  182. data/lib/linked_rails/middleware/linked_data_params.rb +224 -0
  183. data/lib/linked_rails/model/collections.rb +82 -0
  184. data/lib/linked_rails/model/dirty.rb +82 -0
  185. data/lib/linked_rails/model/enhancements.rb +61 -0
  186. data/lib/linked_rails/model/filtering.rb +89 -0
  187. data/lib/linked_rails/model/indexable.rb +51 -0
  188. data/lib/linked_rails/model/iri.rb +121 -0
  189. data/lib/linked_rails/model/iri_mapping.rb +69 -0
  190. data/lib/linked_rails/model/serialization.rb +88 -0
  191. data/lib/linked_rails/model/sorting.rb +20 -0
  192. data/lib/linked_rails/model.rb +68 -0
  193. data/lib/linked_rails/params_parser.rb +93 -0
  194. data/lib/linked_rails/policy/attribute_conditions.rb +53 -0
  195. data/lib/linked_rails/policy.rb +189 -0
  196. data/lib/linked_rails/rdf_error.rb +36 -0
  197. data/lib/linked_rails/renderers.rb +46 -0
  198. data/lib/linked_rails/routes.rb +108 -0
  199. data/lib/linked_rails/serializer.rb +137 -0
  200. data/lib/linked_rails/translate.rb +176 -0
  201. data/lib/linked_rails/version.rb +5 -0
  202. data/lib/linked_rails/vocab.rb +81 -0
  203. data/lib/linked_rails.rb +86 -0
  204. data/lib/nill_class_renderer.rb +3 -0
  205. data/lib/rails/welcome_controller.rb +45 -0
  206. data/lib/tasks/linked_rails_tasks.rake +6 -0
  207. metadata +416 -0
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class OntologiesController < LinkedRails.controller_parent_class
5
+ active_response :show
6
+ end
7
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Actions
5
+ module DefaultActions
6
+ module Create
7
+ def has_collection_create_action(overwrite = {}) # rubocop:disable Naming/PredicateName
8
+ has_collection_action(:create, create_collection_options(overwrite))
9
+ end
10
+
11
+ def has_singular_create_action(overwrite = {}) # rubocop:disable Naming/PredicateName
12
+ has_singular_action(:create, create_singular_options(overwrite))
13
+ end
14
+
15
+ private
16
+
17
+ def create_collection_options(overwrite = {})
18
+ default_create_options(
19
+ form: -> { resource.association_class.try(:form_class) },
20
+ object: -> { resource.build_child },
21
+ policy: :create_child?
22
+ ).merge(overwrite)
23
+ end
24
+
25
+ def create_singular_options(overwrite = {})
26
+ default_create_options(
27
+ form: -> { resource.class.try(:form_class) },
28
+ object: -> { resource },
29
+ policy: :create?,
30
+ url: -> { resource.singular_iri }
31
+ ).merge(overwrite)
32
+ end
33
+
34
+ def default_create_options(overwrite = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
35
+ {
36
+ http_method: :post,
37
+ image: 'fa-plus',
38
+ label: lambda do
39
+ item = LinkedRails::Actions::Item.new(resource: result_class.new, tag: :create)
40
+ LinkedRails.translate(:action, :label, item, false).presence ||
41
+ I18n.t("#{association}.type_new", default: "New #{result_class.name.demodulize.humanize}")
42
+ end,
43
+ root_relative_iri: lambda {
44
+ uri = resource.root_relative_iri.dup
45
+ uri.path ||= ''
46
+ uri.path += '/new'
47
+ uri.query = Rack::Utils.parse_nested_query(uri.query).except('display', 'sort').to_param.presence
48
+ uri.to_s
49
+ },
50
+ result: -> { result_class },
51
+ type: lambda {
52
+ [Vocab.ontola["Create::#{result_class}"], Vocab.schema.CreateAction]
53
+ },
54
+ url: -> { resource.iri }
55
+ }.merge(overwrite)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Actions
5
+ module DefaultActions
6
+ module Destroy
7
+ def has_resource_destroy_action(overwrite = {}) # rubocop:disable Naming/PredicateName
8
+ has_resource_action(:destroy, destroy_resource_options(overwrite))
9
+ end
10
+
11
+ def has_singular_destroy_action(overwrite = {}) # rubocop:disable Naming/PredicateName
12
+ has_singular_action(:destroy, destroy_singular_options(overwrite))
13
+ end
14
+
15
+ private
16
+
17
+ def destroy_resource_options(overwrite = {})
18
+ default_destroy_options(overwrite)
19
+ end
20
+
21
+ def destroy_singular_options(overwrite = {})
22
+ default_destroy_options(
23
+ url: -> { resource.singular_iri }
24
+ ).merge(overwrite)
25
+ end
26
+
27
+ def default_destroy_options(overwrite = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
28
+ {
29
+ http_method: :delete,
30
+ image: 'fa-close',
31
+ policy: :destroy?,
32
+ root_relative_iri: lambda {
33
+ uri = resource.root_relative_iri.dup
34
+ uri.path ||= ''
35
+ uri.path += '/delete'
36
+ uri.to_s
37
+ },
38
+ type: [Vocab.schema.Action, Vocab.ontola[:DestroyAction]],
39
+ url: -> { resource.iri(destroy: true) }
40
+ }.merge(overwrite)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Actions
5
+ module DefaultActions
6
+ module Update
7
+ def has_resource_update_action(overwrite = {}) # rubocop:disable Naming/PredicateName
8
+ has_resource_action(:update, update_resource_options(overwrite))
9
+ end
10
+
11
+ def has_singular_update_action(overwrite = {}) # rubocop:disable Naming/PredicateName
12
+ has_singular_action(:update, update_singular_options(overwrite))
13
+ end
14
+
15
+ private
16
+
17
+ def update_resource_options(overwrite = {})
18
+ default_update_options(overwrite)
19
+ end
20
+
21
+ def update_singular_options(overwrite = {})
22
+ default_update_options(
23
+ url: -> { resource.singular_iri }
24
+ ).merge(overwrite)
25
+ end
26
+
27
+ def default_update_options(overwrite = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
28
+ {
29
+ form: -> { resource.class.try(:form_class) },
30
+ http_method: :put,
31
+ image: 'fa-pencil-square-o',
32
+ label: lambda {
33
+ type = I18n.t("#{resource.class.name.tableize}.type", default: nil)
34
+ type.present? ? I18n.t('edit_type', type: type) : I18n.t('update')
35
+ },
36
+ policy: :update?,
37
+ root_relative_iri: lambda {
38
+ uri = resource.root_relative_iri.dup
39
+ uri.path ||= ''
40
+ uri.path += '/edit'
41
+ uri.to_s
42
+ },
43
+ type: Vocab.schema.UpdateAction,
44
+ url: -> { resource.iri }
45
+ }.merge(overwrite)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'default_actions/create'
4
+
5
+ module LinkedRails
6
+ module Actions
7
+ module DefaultActions
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ extend LinkedRails::Actions::DefaultActions::Create
12
+ extend LinkedRails::Actions::DefaultActions::Destroy
13
+ extend LinkedRails::Actions::DefaultActions::Update
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pundit'
4
+
5
+ module LinkedRails
6
+ module Actions
7
+ class Item # rubocop:disable Metrics/ClassLength
8
+ include ActiveModel::Model
9
+ include LinkedRails::Model
10
+ enhance LinkedRails::Enhancements::Singularable
11
+
12
+ attr_accessor :list, :policy_arguments, :submit_label
13
+ attr_writer :parent, :resource, :root_relative_iri, :user_context, :object,
14
+ :target
15
+ 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|
19
+ attr_writer method
20
+ define_method method do
21
+ var = instance_variable_get(:"@#{method}")
22
+ value = var.respond_to?(:call) ? list.instance_exec(&var) : var
23
+ return instance_variable_set(:"@#{method}", value).presence if value
24
+
25
+ send("#{method}_fallback") if respond_to?("#{method}_fallback", true)
26
+ end
27
+ end
28
+
29
+ def action_status
30
+ @action_status ||=
31
+ if completed
32
+ Vocab.schema.CompletedActionStatus
33
+ elsif policy_valid?
34
+ Vocab.schema.PotentialActionStatus
35
+ elsif policy_expired?
36
+ Vocab.ontola[:ExpiredActionStatus]
37
+ else
38
+ Vocab.ontola[:DisabledActionStatus]
39
+ end
40
+ end
41
+
42
+ def as_json(_opts = {})
43
+ {}
44
+ end
45
+
46
+ def available?
47
+ return false unless action_status == Vocab.schema.PotentialActionStatus
48
+
49
+ @condition.nil? || condition
50
+ end
51
+
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
+ def error
61
+ policy_message ||
62
+ I18n.t("actions.status.#{action_status.to_s.split('#').last}", default: nil)
63
+ end
64
+
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
+ def object
79
+ @object = list.instance_exec(&@object) if @object.respond_to?(:call)
80
+
81
+ @object || resource
82
+ end
83
+
84
+ def parent
85
+ return @parent if instance_variable_defined?(:@parent)
86
+
87
+ if resource.is_a?(LinkedRails.collection_class)
88
+ resource.parent
89
+ else
90
+ resource
91
+ end
92
+ end
93
+
94
+ def policy_message
95
+ resource_policy.try(:message) if action_status == Vocab.ontola[:DisabledActionStatus]
96
+ end
97
+
98
+ def root_relative_iri(_opts = {})
99
+ value = root_relative_iri_from_var
100
+ value = RDF::URI(value) unless value.blank? || value.is_a?(RDF::URI)
101
+ return @root_relative_iri = value if value
102
+
103
+ super
104
+ end
105
+
106
+ def root_relative_singular_iri
107
+ value = root_relative_iri.to_s.sub(resource.root_relative_iri, resource.root_relative_singular_iri)
108
+
109
+ RDF::URI(value)
110
+ end
111
+
112
+ def preview_includes
113
+ [:target, included_object: form_resource_includes]
114
+ end
115
+
116
+ def singular_resource?
117
+ resource.try(:singular_resource?)
118
+ end
119
+
120
+ def iri_opts
121
+ resource&.iri_opts || {}
122
+ end
123
+
124
+ def iri_template
125
+ path_suffix = path.blank? ? "/actions/#{tag}" : "/#{path}"
126
+
127
+ return @iri_template ||= URITemplate.new(path_suffix) if resource.blank?
128
+
129
+ @iri_template ||= iri_template_expand_path(resource.send(:iri_template), path_suffix)
130
+ end
131
+
132
+ def rdf_type
133
+ type
134
+ end
135
+
136
+ def target
137
+ @target ||= LinkedRails.entry_point_class.new(parent: self)
138
+ end
139
+
140
+ def user_context
141
+ @user_context || list.user_context
142
+ end
143
+
144
+ private
145
+
146
+ def description_fallback
147
+ LinkedRails.translate(:action, :description, self, false)
148
+ end
149
+
150
+ def label_fallback
151
+ LinkedRails.translate(:action, :label, self)
152
+ end
153
+
154
+ def policy_expired?
155
+ @policy_expired ||= policy && resource_policy.try(:expired?)
156
+ end
157
+
158
+ def policy_resource_fallback
159
+ resource
160
+ end
161
+
162
+ def policy_valid?
163
+ return true if policy.blank?
164
+ return false if policy_resource.blank?
165
+
166
+ @policy_valid ||= resource_policy.send(policy, *policy_arguments)
167
+ end
168
+
169
+ def predicate_fallback
170
+ Vocab.ontola["#{tag}_action".camelize(:lower)]
171
+ end
172
+
173
+ def resource_fallback
174
+ list&.resource
175
+ end
176
+
177
+ def resource_policy
178
+ @resource_policy ||= Pundit.policy!(user_context, policy_resource) if policy_resource
179
+ end
180
+
181
+ def root_relative_iri_from_var
182
+ return list.instance_exec(&@root_relative_iri) if @root_relative_iri.respond_to?(:call)
183
+
184
+ @root_relative_iri
185
+ end
186
+
187
+ def type_fallback
188
+ Vocab.schema.UpdateAction
189
+ end
190
+
191
+ class << self
192
+ def app_action_list_class
193
+ return @app_action_list_class if instance_variables.include?(:@app_action_list_class)
194
+
195
+ @app_action_list_class = 'AppActionList'.safe_constantize
196
+ end
197
+
198
+ def app_action_list(user_context)
199
+ app_action_list_class&.new(
200
+ resource: nil,
201
+ user_context: user_context
202
+ )
203
+ end
204
+
205
+ 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]
216
+ )
217
+ end
218
+
219
+ def requested_single_resource(params, user_context)
220
+ return nil if params[:id].blank?
221
+
222
+ parent = parent_from_params(params, user_context)
223
+ action_list = parent ? parent.action_list(user_context) : app_action_list(user_context)
224
+
225
+ action_list&.action(params[:id].to_sym)
226
+ end
227
+
228
+ def route_key
229
+ :actions
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'item'
4
+
5
+ module LinkedRails
6
+ module Actions
7
+ class List
8
+ include ActiveModel::Model
9
+ include LinkedRails::Model
10
+ include DefaultActions
11
+ extend LinkedRails::Enhanceable
12
+
13
+ attr_accessor :resource, :user_context
14
+ class_attribute :_defined_actions, instance_reader: false, instance_writer: false
15
+
16
+ def actions
17
+ @actions ||= defined_actions.map { |tag, opts| action_item(tag, opts.dup) }
18
+ end
19
+
20
+ def action(tag)
21
+ action_item(tag, defined_actions[tag].dup) if defined_actions.key?(tag)
22
+ end
23
+
24
+ def defined_actions
25
+ if resource.is_a?(LinkedRails.collection_class)
26
+ self.class.collection_actions
27
+ elsif resource.try(:singular_resource?)
28
+ self.class.singular_actions
29
+ else
30
+ self.class.resource_actions
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def action_item(tag, options)
37
+ options[:tag] ||= options[:action_tag] || tag
38
+ options[:list] ||= self
39
+ LinkedRails.actions_item_class.new(options.except(:action_tag))
40
+ end
41
+
42
+ def association
43
+ @association ||= result_class.to_s.demodulize.tableize
44
+ end
45
+
46
+ def call_option(option, _resource)
47
+ option.respond_to?(:call) ? instance_exec(&option) : option
48
+ end
49
+
50
+ def result_class
51
+ @result_class ||= self.class.actionable_class
52
+ end
53
+
54
+ 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
+ def collection_actions
62
+ defined_actions[:collection]
63
+ end
64
+
65
+ def defined_actions
66
+ initialize_actions
67
+ _defined_actions || initial_defined_actions
68
+ end
69
+
70
+ def resource_actions
71
+ defined_actions[:resource]
72
+ end
73
+
74
+ def singular_actions
75
+ defined_actions[:singular]
76
+ end
77
+
78
+ private
79
+
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
+ def initial_defined_actions(clone_from = {})
96
+ {
97
+ collection: clone_from[:collection].dup || {},
98
+ resource: clone_from[:resource].dup || {},
99
+ singular: clone_from[:singular].dup || {}
100
+ }
101
+ end
102
+
103
+ def initialize_actions
104
+ return if _defined_actions && method(:_defined_actions).owner == singleton_class
105
+
106
+ self._defined_actions = initial_defined_actions(superclass.try(:_defined_actions) || {})
107
+ end
108
+ end
109
+
110
+ enhanceable :actionable_class, :Action
111
+ end
112
+ end
113
+ end