linked_rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +65 -0
- data/Rakefile +34 -0
- data/app/controllers/linked_rails/actions/items_controller.rb +9 -0
- data/app/controllers/linked_rails/bulk_controller.rb +195 -0
- data/app/controllers/linked_rails/current_user_controller.rb +13 -0
- data/app/controllers/linked_rails/enum_values_controller.rb +49 -0
- data/app/controllers/linked_rails/forms_controller.rb +13 -0
- data/app/controllers/linked_rails/manifests_controller.rb +21 -0
- data/app/controllers/linked_rails/menus/items_controller.rb +9 -0
- data/app/controllers/linked_rails/menus/lists_controller.rb +9 -0
- data/app/controllers/linked_rails/not_found_controller.rb +15 -0
- data/app/controllers/linked_rails/ontologies_controller.rb +7 -0
- data/app/models/linked_rails/actions/default_actions/create.rb +60 -0
- data/app/models/linked_rails/actions/default_actions/destroy.rb +45 -0
- data/app/models/linked_rails/actions/default_actions/update.rb +50 -0
- data/app/models/linked_rails/actions/default_actions.rb +17 -0
- data/app/models/linked_rails/actions/item.rb +234 -0
- data/app/models/linked_rails/actions/list.rb +113 -0
- data/app/models/linked_rails/collection/filter.rb +16 -0
- data/app/models/linked_rails/collection/filter_field.rb +30 -0
- data/app/models/linked_rails/collection/filter_option.rb +17 -0
- data/app/models/linked_rails/collection/filterable.rb +92 -0
- data/app/models/linked_rails/collection/infinite_view.rb +98 -0
- data/app/models/linked_rails/collection/iri.rb +74 -0
- data/app/models/linked_rails/collection/iri_mapping.rb +33 -0
- data/app/models/linked_rails/collection/paginated_view.rb +41 -0
- data/app/models/linked_rails/collection/sortable.rb +60 -0
- data/app/models/linked_rails/collection/sorting.rb +72 -0
- data/app/models/linked_rails/collection/view.rb +101 -0
- data/app/models/linked_rails/collection.rb +220 -0
- data/app/models/linked_rails/condition.rb +7 -0
- data/app/models/linked_rails/creative_work.rb +21 -0
- data/app/models/linked_rails/current_user.rb +28 -0
- data/app/models/linked_rails/entry_point.rb +53 -0
- data/app/models/linked_rails/enum_value.rb +33 -0
- data/app/models/linked_rails/form/field/association_input.rb +23 -0
- data/app/models/linked_rails/form/field/checkbox_group.rb +10 -0
- data/app/models/linked_rails/form/field/checkbox_input.rb +10 -0
- data/app/models/linked_rails/form/field/color_input.rb +17 -0
- data/app/models/linked_rails/form/field/date_input.rb +10 -0
- data/app/models/linked_rails/form/field/date_time_input.rb +10 -0
- data/app/models/linked_rails/form/field/email_input.rb +10 -0
- data/app/models/linked_rails/form/field/file_input.rb +10 -0
- data/app/models/linked_rails/form/field/location_input.rb +11 -0
- data/app/models/linked_rails/form/field/markdown_input.rb +10 -0
- data/app/models/linked_rails/form/field/number_input.rb +10 -0
- data/app/models/linked_rails/form/field/password_input.rb +10 -0
- data/app/models/linked_rails/form/field/postal_range_input.rb +10 -0
- data/app/models/linked_rails/form/field/radio_group.rb +10 -0
- data/app/models/linked_rails/form/field/resource_field.rb +23 -0
- data/app/models/linked_rails/form/field/select_input.rb +11 -0
- data/app/models/linked_rails/form/field/slider_input.rb +10 -0
- data/app/models/linked_rails/form/field/text_area_input.rb +10 -0
- data/app/models/linked_rails/form/field/text_input.rb +10 -0
- data/app/models/linked_rails/form/field/toggle_button_group.rb +10 -0
- data/app/models/linked_rails/form/field.rb +117 -0
- data/app/models/linked_rails/form/field_factory.rb +219 -0
- data/app/models/linked_rails/form/group.rb +39 -0
- data/app/models/linked_rails/form/page.rb +31 -0
- data/app/models/linked_rails/form.rb +156 -0
- data/app/models/linked_rails/manifest.rb +102 -0
- data/app/models/linked_rails/media_object.rb +31 -0
- data/app/models/linked_rails/menus/item.rb +92 -0
- data/app/models/linked_rails/menus/list.rb +138 -0
- data/app/models/linked_rails/ontology/base.rb +50 -0
- data/app/models/linked_rails/ontology/class.rb +43 -0
- data/app/models/linked_rails/ontology/property.rb +19 -0
- data/app/models/linked_rails/ontology.rb +34 -0
- data/app/models/linked_rails/property_query.rb +11 -0
- data/app/models/linked_rails/resource.rb +17 -0
- data/app/models/linked_rails/sequence.rb +64 -0
- data/app/models/linked_rails/shacl/node_shape.rb +21 -0
- data/app/models/linked_rails/shacl/property_shape.rb +53 -0
- data/app/models/linked_rails/shacl/shape.rb +33 -0
- data/app/models/linked_rails/web_page.rb +22 -0
- data/app/models/linked_rails/web_site.rb +17 -0
- data/app/models/linked_rails/widget.rb +55 -0
- data/app/policies/linked_rails/actions/item_policy.rb +11 -0
- data/app/policies/linked_rails/actions/list_policy.rb +11 -0
- data/app/policies/linked_rails/collection/view_policy.rb +13 -0
- data/app/policies/linked_rails/collection_policy.rb +41 -0
- data/app/policies/linked_rails/enum_value_policy.rb +32 -0
- data/app/policies/linked_rails/menus/item_policy.rb +11 -0
- data/app/policies/linked_rails/menus/list_policy.rb +11 -0
- data/app/policies/linked_rails/sequence_policy.rb +9 -0
- data/app/serializers/linked_rails/actions/item_serializer.rb +28 -0
- data/app/serializers/linked_rails/collection/filter_field_serializer.rb +12 -0
- data/app/serializers/linked_rails/collection/filter_option_serializer.rb +12 -0
- data/app/serializers/linked_rails/collection/filter_serializer.rb +13 -0
- data/app/serializers/linked_rails/collection/sorting_serializer.rb +13 -0
- data/app/serializers/linked_rails/collection/view_serializer.rb +22 -0
- data/app/serializers/linked_rails/collection_serializer.rb +44 -0
- data/app/serializers/linked_rails/condition_serializer.rb +9 -0
- data/app/serializers/linked_rails/creative_work_serializer.rb +10 -0
- data/app/serializers/linked_rails/current_user_serializer.rb +7 -0
- data/app/serializers/linked_rails/entry_point_serializer.rb +20 -0
- data/app/serializers/linked_rails/enum_value_serializer.rb +12 -0
- data/app/serializers/linked_rails/form/field/association_input_serializer.rb +13 -0
- data/app/serializers/linked_rails/form/field/resource_field_serializer.rb +11 -0
- data/app/serializers/linked_rails/form/field/select_input_serializer.rb +11 -0
- data/app/serializers/linked_rails/form/field_serializer.rb +39 -0
- data/app/serializers/linked_rails/form/group_serializer.rb +14 -0
- data/app/serializers/linked_rails/form/page_serializer.rb +13 -0
- data/app/serializers/linked_rails/form_serializer.rb +9 -0
- data/app/serializers/linked_rails/media_object_serializer.rb +17 -0
- data/app/serializers/linked_rails/menus/item_serializer.rb +35 -0
- data/app/serializers/linked_rails/menus/list_serializer.rb +13 -0
- data/app/serializers/linked_rails/ontology/class_serializer.rb +19 -0
- data/app/serializers/linked_rails/ontology/property_serializer.rb +16 -0
- data/app/serializers/linked_rails/ontology_serializer.rb +8 -0
- data/app/serializers/linked_rails/rdf_error_serializer.rb +8 -0
- data/app/serializers/linked_rails/sequence_serializer.rb +14 -0
- data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +12 -0
- data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +38 -0
- data/app/serializers/linked_rails/shacl/shape_serializer.rb +25 -0
- data/app/serializers/linked_rails/web_page_serializer.rb +10 -0
- data/app/serializers/linked_rails/web_site_serializer.rb +11 -0
- data/app/serializers/linked_rails/widget_serializer.rb +15 -0
- data/config/initializers/inflections.rb +5 -0
- data/lib/generators/linked_rails/install/install_generator.rb +65 -0
- data/lib/generators/linked_rails/install/templates/app_menu_list.rb +41 -0
- data/lib/generators/linked_rails/install/templates/application_action_list.rb +3 -0
- data/lib/generators/linked_rails/install/templates/application_form.rb +3 -0
- data/lib/generators/linked_rails/install/templates/application_menu_list.rb +3 -0
- data/lib/generators/linked_rails/install/templates/application_policy.rb +18 -0
- data/lib/generators/linked_rails/install/templates/application_serializer.rb +5 -0
- data/lib/generators/linked_rails/install/templates/initializer.rb +9 -0
- data/lib/generators/linked_rails/install/templates/locales.yml +12 -0
- data/lib/generators/linked_rails/install/templates/rdf_responder.rb +5 -0
- data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +5 -0
- data/lib/generators/linked_rails/install/templates/vocab.rb +5 -0
- data/lib/generators/linked_rails/install/templates/vocab.yml +26 -0
- data/lib/generators/linked_rails/model/model_generator.rb +58 -0
- data/lib/generators/linked_rails/model/templates/action_list.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/controller.rb.tt +7 -0
- data/lib/generators/linked_rails/model/templates/create_table_migration.rb.tt +24 -0
- data/lib/generators/linked_rails/model/templates/form.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/model.rb.tt +15 -0
- data/lib/generators/linked_rails/model/templates/module.rb.tt +7 -0
- data/lib/generators/linked_rails/model/templates/policy.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/serializer.rb.tt +9 -0
- data/lib/linked_rails/active_response/controller/collections.rb +43 -0
- data/lib/linked_rails/active_response/controller/crud_defaults.rb +92 -0
- data/lib/linked_rails/active_response/controller/params.rb +51 -0
- data/lib/linked_rails/active_response/controller.rb +37 -0
- data/lib/linked_rails/active_response/responders/rdf.rb +158 -0
- data/lib/linked_rails/cache.rb +35 -0
- data/lib/linked_rails/callable_variable.rb +25 -0
- data/lib/linked_rails/constraints/whitelist.rb +36 -0
- data/lib/linked_rails/controller/authorization.rb +15 -0
- data/lib/linked_rails/controller/error_handling.rb +76 -0
- data/lib/linked_rails/controller.rb +43 -0
- data/lib/linked_rails/engine.rb +7 -0
- data/lib/linked_rails/enhanceable.rb +21 -0
- data/lib/linked_rails/enhancements/actionable/model.rb +71 -0
- data/lib/linked_rails/enhancements/actionable/serializer.rb +25 -0
- data/lib/linked_rails/enhancements/creatable/action.rb +15 -0
- data/lib/linked_rails/enhancements/creatable/controller.rb +15 -0
- data/lib/linked_rails/enhancements/destroyable/action.rb +15 -0
- data/lib/linked_rails/enhancements/destroyable/controller.rb +15 -0
- data/lib/linked_rails/enhancements/destroyable/routing.rb +19 -0
- data/lib/linked_rails/enhancements/indexable/model.rb +10 -0
- data/lib/linked_rails/enhancements/menuable/model.rb +36 -0
- data/lib/linked_rails/enhancements/menuable/serializer.rb +33 -0
- data/lib/linked_rails/enhancements/route_concerns.rb +56 -0
- data/lib/linked_rails/enhancements/singularable/controller.rb +43 -0
- data/lib/linked_rails/enhancements/singularable/model.rb +47 -0
- data/lib/linked_rails/enhancements/singularable/serializer.rb +28 -0
- data/lib/linked_rails/enhancements/tableable/model.rb +28 -0
- data/lib/linked_rails/enhancements/updatable/action.rb +15 -0
- data/lib/linked_rails/enhancements/updatable/controller.rb +15 -0
- data/lib/linked_rails/enhancements/updatable/routing.rb +20 -0
- data/lib/linked_rails/enhancements/updatable/serializer.rb +17 -0
- data/lib/linked_rails/enhancements.rb +22 -0
- data/lib/linked_rails/helpers/delta_helper.rb +86 -0
- data/lib/linked_rails/helpers/ontola_actions_helper.rb +32 -0
- data/lib/linked_rails/helpers/resource_helper.rb +70 -0
- data/lib/linked_rails/iri_mapper.rb +125 -0
- data/lib/linked_rails/middleware/linked_data_params.rb +224 -0
- data/lib/linked_rails/model/collections.rb +82 -0
- data/lib/linked_rails/model/dirty.rb +82 -0
- data/lib/linked_rails/model/enhancements.rb +61 -0
- data/lib/linked_rails/model/filtering.rb +89 -0
- data/lib/linked_rails/model/indexable.rb +51 -0
- data/lib/linked_rails/model/iri.rb +121 -0
- data/lib/linked_rails/model/iri_mapping.rb +69 -0
- data/lib/linked_rails/model/serialization.rb +88 -0
- data/lib/linked_rails/model/sorting.rb +20 -0
- data/lib/linked_rails/model.rb +68 -0
- data/lib/linked_rails/params_parser.rb +93 -0
- data/lib/linked_rails/policy/attribute_conditions.rb +53 -0
- data/lib/linked_rails/policy.rb +189 -0
- data/lib/linked_rails/rdf_error.rb +36 -0
- data/lib/linked_rails/renderers.rb +46 -0
- data/lib/linked_rails/routes.rb +108 -0
- data/lib/linked_rails/serializer.rb +137 -0
- data/lib/linked_rails/translate.rb +176 -0
- data/lib/linked_rails/version.rb +5 -0
- data/lib/linked_rails/vocab.rb +81 -0
- data/lib/linked_rails.rb +86 -0
- data/lib/nill_class_renderer.rb +3 -0
- data/lib/rails/welcome_controller.rb +45 -0
- data/lib/tasks/linked_rails_tasks.rake +6 -0
- 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
|