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,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class Cache
5
+ extend RDF::Serializers::HextupleSerializer
6
+
7
+ class << self
8
+ def invalidate(iri)
9
+ write([invalidate_resource(iri)])
10
+ end
11
+
12
+ def invalidate_all
13
+ invalidate(Vocab.sp.Variable)
14
+ end
15
+
16
+ def write(delta)
17
+ Redis.new.publish(
18
+ ENV['CACHE_CHANNEL'],
19
+ delta.map { |s| Oj.fast_generate(value_to_hex(*s)) }.join("\n")
20
+ )
21
+ end
22
+
23
+ private
24
+
25
+ def invalidate_resource(iri)
26
+ [
27
+ Vocab.sp.Variable,
28
+ Vocab.sp.Variable,
29
+ Vocab.sp.Variable,
30
+ LinkedRails::Vocab.ontola["invalidate?graph=#{CGI.escape(iri)}"]
31
+ ]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module CallableVariable
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def callable_variable(method, opts = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
9
+ variable ||= opts[:variable] || method
10
+ default ||= opts[:default]
11
+
12
+ define_method method do
13
+ value = instance_variable_get("@#{variable}")
14
+ if value.respond_to?(:call)
15
+ instance = opts[:instance] ? send(opts[:instance]) : self
16
+ value = instance_variable_set("@#{variable}", instance.instance_exec(&value))
17
+ end
18
+ return value if !value.nil? || default.blank?
19
+
20
+ instance_exec(&default)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Constraints
5
+ module Whitelist
6
+ module_function
7
+
8
+ def matches?(request)
9
+ return true unless LinkedRails.whitelisted_spi_ips
10
+
11
+ ip = request_ip(request.ip)
12
+ remote_ip = request_ip(request.remote_ip)
13
+
14
+ allowed = [ip, remote_ip].all? do |req_ip|
15
+ LinkedRails.whitelisted_spi_ips.any? { |allowed_ip| allowed_ip.include?(req_ip) }
16
+ end
17
+ log_verdict(allowed, request, ip, remote_ip)
18
+
19
+ allowed
20
+ end
21
+
22
+ def log_verdict(allowed, request, ip, remote_ip)
23
+ return if Rails.env.production?
24
+
25
+ verdict = allowed ? 'pass' : 'fail'
26
+ Rails.logger.debug("[WhitelistConstraint] #{verdict} for #{request.url} by ip: #{ip}, remote ip: #{remote_ip}")
27
+ end
28
+
29
+ def request_ip(ip)
30
+ return nil unless ip.is_a?(String) && ip.present?
31
+
32
+ IPAddr.new(ip)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Controller
5
+ module Authorization
6
+ extend ActiveSupport::Concern
7
+
8
+ def authorize_action
9
+ query = action_name == 'index' ? :show? : "#{params[:action].chomp('!')}?"
10
+
11
+ authorize(current_resource!, query)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Controller
5
+ module ErrorHandling
6
+ extend ActiveSupport::Concern
7
+ included do
8
+ rescue_from StandardError, with: :handle_and_report_error
9
+ rescue_from ActiveRecord::RecordNotFound, with: :handle_error
10
+ rescue_from Pundit::NotAuthorizedError, with: :handle_error
11
+ end
12
+
13
+ private
14
+
15
+ def add_error_snackbar(error)
16
+ add_exec_action_header(response.headers, ontola_snackbar_action(error.error.message))
17
+ end
18
+
19
+ def add_error_snackbar?(_error)
20
+ !%w[GET HEAD].include?(request.method)
21
+ end
22
+
23
+ def handle_error(error)
24
+ respond_to do |format|
25
+ (LinkedRails::Renderers.rdf_content_types + [:json]).each do |type|
26
+ format.send(type) { error_response_serializer(error, type) }
27
+ end
28
+ end
29
+ end
30
+
31
+ def handle_and_report_error(error)
32
+ raise if Rails.env.development? || Rails.env.test?
33
+ raise if response_body
34
+
35
+ handle_error(error)
36
+ end
37
+
38
+ def error_mode(exception)
39
+ @_error_mode = true
40
+ Rails.logger.error exception
41
+ @_uc = nil
42
+ end
43
+
44
+ def error_resource(status, error, url = request.original_url)
45
+ LinkedRails.rdf_error_class.new(status, url, error)
46
+ end
47
+
48
+ def error_response_serializer(error, type, status: nil)
49
+ status ||= error_status(error)
50
+ error = error_resource(status, error)
51
+ add_error_snackbar(error) if add_error_snackbar?(error)
52
+ render type => error, status: status
53
+ end
54
+
55
+ def error_status(error)
56
+ self.class.error_status_codes[error.class.to_s] || 500
57
+ end
58
+
59
+ module ClassMethods
60
+ def error_status_codes # rubocop:disable Metrics/MethodLength
61
+ @error_status_codes ||= {
62
+ 'ActionController::ParameterMissing' => 422,
63
+ 'ActionController::RoutingError' => 404,
64
+ 'ActionController::UnpermittedParameters' => 422,
65
+ 'ActiveRecord::RecordNotFound' => 404,
66
+ 'ActiveRecord::RecordNotUnique' => 304,
67
+ 'Doorkeeper::Errors::InvalidGrantReuse' => 422,
68
+ 'LinkedRails::Auth::Errors::Expired' => 410,
69
+ 'LinkedRails::Auth::Errors::Unauthorized' => 401,
70
+ 'Pundit::NotAuthorizedError' => 403
71
+ }
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'active_response/controller'
4
+ require_relative 'controller/authorization'
5
+ require_relative 'controller/error_handling'
6
+
7
+ module LinkedRails
8
+ module Controller
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ extend Enhanceable
13
+
14
+ enhanceable :controller_class, :Controller
15
+
16
+ include LinkedRails::ActiveResponse::Controller
17
+ include LinkedRails::Controller::Authorization
18
+ include LinkedRails::Controller::ErrorHandling
19
+ include LinkedRails::Helpers::OntolaActionsHelper
20
+ include LinkedRails::Helpers::DeltaHelper
21
+ include LinkedRails::Helpers::ResourceHelper
22
+
23
+ before_action :set_manifest_header
24
+ end
25
+
26
+ private
27
+
28
+ def controller_class
29
+ self.class.controller_class
30
+ end
31
+
32
+ def set_manifest_header
33
+ response.headers['Manifest'] = LinkedRails.iri(path: '/manifest.json')
34
+ end
35
+
36
+ module ClassMethods
37
+ def controller_class
38
+ @controller_class ||=
39
+ name.sub(/Controller$/, '').classify.safe_constantize || controller_name.classify.safe_constantize
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace LinkedRails
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhanceable
5
+ def include_enhancements(klass_method, enhanceable)
6
+ send(klass_method)
7
+ .try(:enhancement_modules, enhanceable)
8
+ &.reject { |mod| include? mod }
9
+ &.each { |mod| include mod }
10
+ end
11
+
12
+ def enhanceable(klass_method, enhanceable)
13
+ include_enhancements(klass_method, enhanceable)
14
+
15
+ define_singleton_method('inherited') do |target|
16
+ super(target)
17
+ target.include_enhancements(klass_method, enhanceable) if target.name
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Actionable
6
+ module Model
7
+ extend ActiveSupport::Concern
8
+
9
+ def actions(user_context = nil)
10
+ action_list(user_context).actions
11
+ end
12
+
13
+ def action(tag, user_context = nil)
14
+ actions(user_context).find { |a| a.tag == tag }
15
+ end
16
+
17
+ def action_list(user_context)
18
+ @action_list ||= {}
19
+ @action_list[user_context] ||= self.class.action_list.new(resource: self, user_context: user_context)
20
+ end
21
+
22
+ def action_triples
23
+ @action_triples ||= triples_for_actions(actions) + triples_for_actions(collection_actions)
24
+ end
25
+
26
+ def collection_actions
27
+ (try(:collections) || []).map do |opts|
28
+ collection_for(opts[:name]).actions
29
+ end.flatten
30
+ end
31
+
32
+ private
33
+
34
+ def triples_for_actions(actions)
35
+ actions.flat_map do |action|
36
+ triples = [
37
+ [iri, action.predicate, action.iri],
38
+ [iri, Vocab.schema.potentialAction, action.iri]
39
+ ]
40
+ triples << [iri, LinkedRails::Vocab.ontola[:favoriteAction], action.iri] if action.favorite
41
+ triples
42
+ end
43
+ end
44
+
45
+ module ClassMethods
46
+ def action_list
47
+ return @action_list if @action_list.try(:actionable_class) == self
48
+
49
+ @action_list = defined_action_list || define_action_list
50
+ end
51
+
52
+ private
53
+
54
+ def action_superclass
55
+ superclass.try(:action_list) || LinkedRails.action_list_parent_class
56
+ end
57
+
58
+ def defined_action_list
59
+ "#{name}ActionList".safe_constantize
60
+ end
61
+
62
+ def define_action_list
63
+ list = const_set("#{name.demodulize}ActionList", Class.new(action_superclass))
64
+ list.include_enhancements(:actionable_class, :Action)
65
+ list
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Actionable
6
+ module Serializer
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ statements :action_triples
11
+ end
12
+
13
+ class_methods do
14
+ def action_triples(object, _params)
15
+ if object.iri.anonymous? && !object.singular_resource?
16
+ []
17
+ else
18
+ object.action_triples
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Creatable
6
+ module Action
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ has_collection_create_action
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Creatable
6
+ module Controller
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ active_response :create
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Destroyable
6
+ module Action
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ has_resource_destroy_action
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Destroyable
6
+ module Controller
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ active_response :destroy
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Enhancements
5
+ module Destroyable
6
+ module Routing; end
7
+
8
+ class << self
9
+ def route_concerns(mapper)
10
+ mapper.concern :destroyable do
11
+ mapper.member do
12
+ mapper.delete '', action: :destroy
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end