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,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Collections
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_attribute :collections
10
+ end
11
+
12
+ # Initialises a {Collection} for one of the collections defined by {has_collection}
13
+ # @see Ldable#has_collection
14
+ # @param [Hash] name as defined with {has_collection}
15
+ # @param [Class] user_context
16
+ # @param [Hash] filter
17
+ # @param [Integer, String] page
18
+ # @param [ApplicationRecord] part_of
19
+ # @param [Hash] opts Additional options to be passed to the collection.
20
+ # @return [Collection]
21
+ def collection_for(name, instance_opts = {})
22
+ collection_opts = collections.detect { |c| c[:name] == name }.try(:[], :options).dup
23
+ return if collection_opts.blank?
24
+
25
+ collection_opts[:name] = name
26
+ collection_opts[:parent] = self
27
+ collection_opts[:part_of] = collection_opts.key?(:part_of) ? send(collection_opts[:part_of]) : self
28
+ collection_class = collection_opts.delete(:collection_class) || LinkedRails.collection_class
29
+ collection_class.collection_or_view(collection_opts, instance_opts)
30
+ end
31
+
32
+ def parent_collections(user_context)
33
+ return [] if try(:parent).try(:collections).blank?
34
+
35
+ parent_collections_for(parent, user_context)
36
+ end
37
+
38
+ private
39
+
40
+ def parent_collections_for(parent, user_context)
41
+ parent
42
+ .collections
43
+ .select { |collection| is_a?(collection[:options][:association_class]) }
44
+ .map { |collection| parent.collection_for(collection[:name], user_context: user_context) }
45
+ end
46
+
47
+ module ClassMethods
48
+ def collections_add(opts)
49
+ initialize_collections
50
+ collections.delete_if { |c| c[:name] == opts[:name] }
51
+ collections.append(opts)
52
+ end
53
+
54
+ def initialize_collections
55
+ return if collections && method(:collections).owner == singleton_class
56
+
57
+ self.collections = superclass.try(:collections)&.dup || []
58
+ end
59
+
60
+ # Defines a collection to be used in {collection_for}
61
+ # @see Ldable#collection_for
62
+ # @note Adds a instance_method <name>_collection
63
+ # @param [Hash] name as to be used in {collection_for}
64
+ # @param [Hash] options
65
+ # @option options [Sym] association the name of the association
66
+ # @option options [Class] association_class the class of the association
67
+ # @option options [Sym] joins the associations to join
68
+ # @return [Collection]
69
+ def with_collection(name, options = {})
70
+ options[:association] ||= name.to_sym
71
+ options[:association_class] ||= name.to_s.classify.constantize
72
+
73
+ collections_add(name: name, options: options)
74
+
75
+ define_method "#{name.to_s.singularize}_collection" do |opts = {}|
76
+ collection_for(name, opts)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Dirty
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
10
+ association_has_destructed(association_name) if will_destruct_association?(association_name, attributes)
11
+
12
+ super
13
+ end
14
+
15
+ def assign_nested_attributes_for_collection_association(association_name, attrs)
16
+ attributes = attrs
17
+ attributes = attrs.with_indifferent_access.key?(:id) ? [attrs] : attrs.values if attrs.is_a?(Hash)
18
+
19
+ association_has_destructed(association_name) if will_destruct_association?(association_name, attributes)
20
+
21
+ super
22
+ end
23
+ end
24
+
25
+ def previous_changes_by_predicate
26
+ serializer_class = RDF::Serializers.serializer_for(self)
27
+ return {} unless respond_to?(:previous_changes) && serializer_class
28
+
29
+ Hash[
30
+ previous_changes
31
+ .map { |k, v| [serializer_class.attributes_to_serialize[k.to_sym]&.predicate, v] }
32
+ .select { |k, _v| k.present? }
33
+ ]
34
+ end
35
+
36
+ def previously_changed_relations
37
+ serializer_class = RDF::Serializers.serializer_for(self)
38
+ return {} unless serializer_class.try(:relationships_to_serialize)
39
+
40
+ serializer_class.relationships_to_serialize.select do |key, _value|
41
+ if respond_to?(key)
42
+ association_key = key.to_s.ends_with?('_collection') ? send(key).association : key
43
+ association_has_destructed?(association_key) || association_changed?(association_key)
44
+ end
45
+ end.with_indifferent_access
46
+ end
47
+
48
+ private
49
+
50
+ def association_changed?(association) # rubocop:disable Metrics/AbcSize
51
+ ids_method = "#{association.to_s.singularize}_ids"
52
+ return true if previous_changes.include?("#{association}_id") || previous_changes.include?(ids_method)
53
+ return false unless try(:association_cached?, association)
54
+
55
+ if self.class.reflect_on_association(association).collection?
56
+ send(association).any? { |a| a.previous_changes.present? }
57
+ else
58
+ send(association)&.previous_changes&.present?
59
+ end
60
+ end
61
+
62
+ def association_has_destructed(association_key)
63
+ @destructed_association_members ||= []
64
+ @destructed_association_members << association_key.to_sym
65
+ end
66
+
67
+ def association_has_destructed?(association_key)
68
+ @destructed_association_members&.include?(association_key.to_sym)
69
+ end
70
+
71
+ def will_destruct_association?(association_name, attributes)
72
+ return false unless nested_attributes_options[association_name][:allow_destroy]
73
+
74
+ if attributes.is_a?(Array)
75
+ attributes.any? { |attrs| has_destroy_flag?(attrs.with_indifferent_access) }
76
+ else
77
+ has_destroy_flag?(attributes.with_indifferent_access)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Enhancements
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_attribute :enhancements
10
+ self.enhancements ||= {}
11
+ end
12
+
13
+ def enhanced_with?(enhancement)
14
+ self.class.enhancements.include?(enhancement)
15
+ end
16
+
17
+ module ClassMethods
18
+ # Adds an enhancement to a model and includes the Model module.
19
+ def enhance(enhancement, opts = {})
20
+ initialize_enhancements
21
+ already_included = enhanced_with?(enhancement)
22
+
23
+ self.enhancements[enhancement] = opts
24
+ return if already_included
25
+
26
+ enhance_routing(enhancement) if enhancement.const_defined?(:Routing) && enhanced_with?(enhancement, :Routing)
27
+ include enhancement::Model if enhancement.const_defined?(:Model) && enhanced_with?(enhancement, :Model)
28
+ end
29
+
30
+ def enhanced_with?(enhancement, const = nil)
31
+ return false unless self.enhancements.key?(enhancement)
32
+ return true if const.nil?
33
+
34
+ opts = self.enhancements[enhancement]
35
+
36
+ return opts[:only].include?(const) if opts.key?(:only)
37
+
38
+ !opts.key?(:except) || !opts[:except].include?(const)
39
+ end
40
+
41
+ def enhancement_modules(const)
42
+ enhancements
43
+ .select { |enhancement, _opts| enhancement.const_defined?(const) && enhanced_with?(enhancement, const) }
44
+ .map { |enhancement, _opts| enhancement.const_get(const) }
45
+ end
46
+
47
+ private
48
+
49
+ def enhance_routing(enhancement)
50
+ LinkedRails::Enhancements::RouteConcerns.add_concern(enhancement)
51
+ end
52
+
53
+ def initialize_enhancements
54
+ return if enhancements && method(:enhancements).owner == singleton_class
55
+
56
+ self.enhancements = superclass.try(:enhancements)&.dup || {}
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Filtering
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_attribute :default_filters, instance_accessor: false, instance_predicate: false
10
+ class_attribute :filter_options
11
+ self.default_filters = {}
12
+ end
13
+
14
+ module ClassMethods
15
+ def filter_options
16
+ class_variables.include?(:@@filter_options) ? super : {}
17
+ end
18
+
19
+ def filterable(options = {})
20
+ initialize_filter_options
21
+
22
+ self.filter_options = HashWithIndifferentAccess.new(options).merge(filter_options)
23
+
24
+ options.map { |k, filter| define_filter_method(k, filter) }
25
+ end
26
+
27
+ private
28
+
29
+ def boolean_filter(true_filter, false_filter, options = {})
30
+ {
31
+ filter: resolve_boolean_filter(true_filter, false_filter),
32
+ values: [true, false]
33
+ }.merge(options)
34
+ end
35
+
36
+ def initialize_filter_options
37
+ return if filter_options && method(:filter_options).owner == singleton_class
38
+
39
+ self.filter_options = superclass.try(:filter_options)&.dup || {}
40
+ end
41
+
42
+ def define_filter_method(key, filter)
43
+ method = predicate_mapping[key]&.key
44
+ return if !method || method_defined?(method) || !filter[:attr]
45
+
46
+ enum_map = defined_enums[method.to_s]
47
+
48
+ if enum_map
49
+ define_enum_filter_method(method, filter, enum_map)
50
+ else
51
+ define_plain_filter_method(method, filter)
52
+ end
53
+ end
54
+
55
+ def define_enum_filter_method(key, filter, enum_map)
56
+ define_method key do
57
+ filter[:values].key(enum_map[send(filter[:attr] || key)])
58
+ end
59
+
60
+ define_method "#{key}=" do |value|
61
+ send("#{filter[:attr]}=", enum_map.key(filter[:values][value&.to_sym]))
62
+ end
63
+ end
64
+
65
+ def define_plain_filter_method(key, filter)
66
+ define_method key do
67
+ filter[:values][send(filter[:attr])]
68
+ end
69
+
70
+ define_method "#{key}=" do |value|
71
+ send("#{filter[:attr]}=", filter[:values].key(value))
72
+ end
73
+ end
74
+
75
+ def resolve_boolean_filter(true_filter, false_filter)
76
+ lambda { |scope, values|
77
+ if values.include?(true) && values.include?(false)
78
+ scope
79
+ else
80
+ values.reduce(scope) do |_sub_scope, val|
81
+ val ? true_filter.call(scope) : false_filter.call(scope)
82
+ end
83
+ end
84
+ }
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Indexable
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def collection_from_parent(params)
10
+ parent = parent_from_params(params, params[:user_context])
11
+ return if parent.blank?
12
+
13
+ collection_name = collection_from_parent_name(parent, params)
14
+
15
+ parent.send(collection_name, params) if collection_name
16
+ end
17
+
18
+ def root_collection(params = {})
19
+ return unless root_collection?
20
+
21
+ root_collection_class.collection_or_view(root_collection_opts, params)
22
+ end
23
+
24
+ def root_collection_class
25
+ LinkedRails.collection_class
26
+ end
27
+
28
+ private
29
+
30
+ def collection_from_parent_name(parent, _params)
31
+ collection_name = "#{name.underscore}_collection"
32
+
33
+ collection_name if parent.respond_to?(collection_name, true)
34
+ end
35
+
36
+ def grid_max_columns; end
37
+
38
+ def root_collection_opts
39
+ {
40
+ association_class: self,
41
+ grid_max_columns: grid_max_columns
42
+ }
43
+ end
44
+
45
+ def root_collection?
46
+ true
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Iri
6
+ extend ActiveSupport::Concern
7
+
8
+ def anonymous_iri
9
+ @anonymous_iri ||= RDF::Node.new
10
+ end
11
+
12
+ def anonymous_iri?
13
+ self.class < ActiveRecord::Base && new_record?
14
+ end
15
+
16
+ # @return [RDF::URI].
17
+ def iri(opts = {})
18
+ return anonymous_iri if anonymous_iri?
19
+ return iri_with_root(root_relative_iri(opts)) if opts.present?
20
+
21
+ @iri ||= iri_with_root(root_relative_iri)
22
+ end
23
+
24
+ # @return [Hash]
25
+ def iri_opts
26
+ @iri_opts ||= {
27
+ fragment: route_fragment,
28
+ id: to_param
29
+ }
30
+ end
31
+
32
+ def rdf_type
33
+ self.class.iri
34
+ end
35
+
36
+ def reload(_opts = {})
37
+ @iri = nil
38
+ super
39
+ end
40
+
41
+ # @return [RDF::URI]
42
+ def root_relative_iri(opts = {})
43
+ RDF::URI(expand_iri_template(iri_opts.merge(opts)))
44
+ end
45
+
46
+ # @return [String, Symbol]
47
+ def route_fragment; end
48
+
49
+ private
50
+
51
+ # @return [String]
52
+ def expand_iri_template(args = {})
53
+ iri_template.expand(args)
54
+ end
55
+
56
+ # @return [RDF::URI]
57
+ def iri_with_root(root_relative_iri)
58
+ iri = root_relative_iri.dup
59
+ iri.scheme = LinkedRails.scheme
60
+ iri.host = LinkedRails.host
61
+ iri
62
+ end
63
+
64
+ # @return [URITemplate]
65
+ def iri_template
66
+ self.class.iri_template
67
+ end
68
+
69
+ # @return [URITemplate]
70
+ def iri_template_expand_path(template_base, path)
71
+ tokens = template_base.tokens
72
+
73
+ ind = tokens.find_index do |t|
74
+ t.is_a?(URITemplate::RFC6570::Expression::FormQuery) || t.is_a?(URITemplate::RFC6570::Expression::Fragment)
75
+ end
76
+
77
+ prefix = ind ? tokens[0...ind] : tokens
78
+ suffix = ind ? tokens[ind..-1] : []
79
+ URITemplate.new([prefix, path, suffix].flatten.join)
80
+ end
81
+
82
+ # @return [URITemplate]
83
+ def iri_template_with_fragment(template_base, fragment)
84
+ URITemplate.new("#{template_base.to_s.sub(/{#[\w]+}/, '').split('#').first}##{fragment}")
85
+ end
86
+
87
+ def singular_iri; end
88
+
89
+ def singular_iri_opts
90
+ {}
91
+ end
92
+
93
+ module ClassMethods
94
+ def iri
95
+ @iri ||= iri_namespace[iri_value] if iri_namespace
96
+ end
97
+
98
+ def iri_namespace
99
+ return if self == ApplicationRecord
100
+
101
+ superclass.try(:iri_namespace) ||
102
+ (linked_rails_module? ? Vocab.ontola : LinkedRails.app_vocab)
103
+ end
104
+
105
+ def iri_value
106
+ linked_rails_module? ? name.demodulize : name
107
+ end
108
+
109
+ def iri_template
110
+ @iri_template ||= URITemplate.new("/#{route_key}{/id}{#fragment}")
111
+ end
112
+
113
+ def linked_rails_module?
114
+ (Rails.version < '6' ? parents : module_parents).include?(LinkedRails)
115
+ end
116
+
117
+ delegate :route_key, to: :model_name
118
+ end
119
+ end
120
+ end
121
+ end