linked_rails 0.0.3 → 0.0.4

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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/linked_rails/bulk_controller.rb +26 -6
  3. data/app/controllers/linked_rails/enum_values_controller.rb +0 -42
  4. data/app/models/linked_rails/actions/item.rb +46 -30
  5. data/app/models/linked_rails/actions/list.rb +6 -25
  6. data/app/models/linked_rails/collection/configuration.rb +55 -0
  7. data/app/models/linked_rails/collection/filter.rb +1 -1
  8. data/app/models/linked_rails/collection/filter_field.rb +5 -1
  9. data/app/models/linked_rails/collection/filter_option.rb +1 -1
  10. data/app/models/linked_rails/collection/filterable.rb +3 -8
  11. data/app/models/linked_rails/collection/infinite.rb +102 -0
  12. data/app/models/linked_rails/collection/infinite_view.rb +1 -90
  13. data/app/models/linked_rails/collection/iri.rb +33 -52
  14. data/app/models/linked_rails/collection/iri_mapping.rb +14 -6
  15. data/app/models/linked_rails/collection/paginated.rb +45 -0
  16. data/app/models/linked_rails/collection/paginated_view.rb +1 -33
  17. data/app/models/linked_rails/collection/sortable.rb +1 -9
  18. data/app/models/linked_rails/collection/sorting.rb +1 -1
  19. data/app/models/linked_rails/collection/view.rb +15 -5
  20. data/app/models/linked_rails/collection.rb +33 -67
  21. data/app/models/linked_rails/creative_work.rb +1 -1
  22. data/app/models/linked_rails/entry_point.rb +8 -5
  23. data/app/models/linked_rails/enum_value.rb +39 -1
  24. data/app/models/linked_rails/form/field/resource_field.rb +2 -0
  25. data/app/models/linked_rails/form/field.rb +6 -8
  26. data/app/models/linked_rails/form/field_factory.rb +21 -10
  27. data/app/models/linked_rails/form/group.rb +2 -2
  28. data/app/models/linked_rails/form/page.rb +4 -4
  29. data/app/models/linked_rails/form.rb +13 -15
  30. data/app/models/linked_rails/manifest.rb +8 -2
  31. data/app/models/linked_rails/menus/item.rb +1 -1
  32. data/app/models/linked_rails/menus/list.rb +3 -2
  33. data/app/models/linked_rails/ontology/base.rb +1 -1
  34. data/app/models/linked_rails/ontology/class.rb +3 -3
  35. data/app/models/linked_rails/ontology.rb +5 -5
  36. data/app/models/linked_rails/sequence.rb +2 -2
  37. data/app/models/linked_rails/shacl/property_shape.rb +1 -1
  38. data/app/models/linked_rails/widget.rb +1 -1
  39. data/app/serializers/linked_rails/actions/item_serializer.rb +2 -1
  40. data/app/serializers/linked_rails/collection_serializer.rb +7 -2
  41. data/app/serializers/linked_rails/entry_point_serializer.rb +1 -1
  42. data/app/serializers/linked_rails/ontology_serializer.rb +2 -2
  43. data/lib/generators/linked_rails/install/install_generator.rb +5 -8
  44. data/lib/generators/linked_rails/install/templates/README +2 -0
  45. data/lib/generators/linked_rails/install/templates/app_menu_list.rb +36 -7
  46. data/lib/generators/linked_rails/install/templates/application_menu_list.rb +40 -1
  47. data/lib/generators/linked_rails/install/templates/initializer.rb +1 -2
  48. data/lib/generators/linked_rails/install/templates/locales.yml +12 -0
  49. data/lib/generators/linked_rails/install/templates/vocab.rb +1 -0
  50. data/lib/generators/linked_rails/install/templates/vocab.yml +2 -2
  51. data/lib/generators/linked_rails/model/model_generator.rb +0 -1
  52. data/lib/generators/linked_rails/model/templates/controller.rb.tt +5 -1
  53. data/lib/generators/linked_rails/model/templates/form.rb.tt +3 -0
  54. data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +15 -0
  55. data/lib/generators/linked_rails/model/templates/policy.rb.tt +13 -0
  56. data/lib/generators/linked_rails/model/templates/serializer.rb.tt +1 -1
  57. data/lib/linked_rails/active_response/controller/collections.rb +1 -1
  58. data/lib/linked_rails/active_response/controller/crud_defaults.rb +3 -3
  59. data/lib/linked_rails/active_response/controller/params.rb +5 -5
  60. data/lib/linked_rails/active_response/controller.rb +11 -0
  61. data/lib/linked_rails/active_response/responders/rdf.rb +19 -10
  62. data/lib/linked_rails/callable_variable.rb +1 -1
  63. data/lib/linked_rails/collection_params_parser.rb +93 -0
  64. data/lib/linked_rails/controller/actionable.rb +118 -0
  65. data/lib/linked_rails/controller/authorization.rb +6 -0
  66. data/lib/linked_rails/controller/default_actions/create.rb +52 -0
  67. data/lib/linked_rails/controller/default_actions/destroy.rb +42 -0
  68. data/lib/linked_rails/controller/default_actions/update.rb +43 -0
  69. data/lib/linked_rails/controller.rb +20 -3
  70. data/lib/linked_rails/enhancements/creatable/controller.rb +1 -1
  71. data/lib/linked_rails/enhancements/destroyable/controller.rb +1 -1
  72. data/lib/linked_rails/enhancements/updatable/controller.rb +1 -1
  73. data/lib/linked_rails/enhancements.rb +0 -16
  74. data/lib/linked_rails/helpers/delta_helper.rb +26 -3
  75. data/lib/linked_rails/helpers/ontola_actions_helper.rb +2 -2
  76. data/lib/linked_rails/helpers/resource_helper.rb +1 -1
  77. data/lib/linked_rails/iri_mapper.rb +17 -39
  78. data/lib/linked_rails/middleware/linked_data_params.rb +7 -127
  79. data/lib/linked_rails/model/actionable.rb +69 -0
  80. data/lib/linked_rails/model/collections.rb +195 -39
  81. data/lib/linked_rails/model/dirty.rb +1 -1
  82. data/lib/linked_rails/model/enhancements.rb +1 -6
  83. data/lib/linked_rails/model/filtering.rb +2 -4
  84. data/lib/linked_rails/model/indexable.rb +5 -15
  85. data/lib/linked_rails/model/iri.rb +15 -17
  86. data/lib/linked_rails/model/iri_mapping.rb +35 -6
  87. data/lib/linked_rails/model/menuable.rb +34 -0
  88. data/lib/linked_rails/model/serialization.rb +0 -9
  89. data/lib/linked_rails/model/singularable.rb +55 -0
  90. data/lib/linked_rails/model/sorting.rb +0 -5
  91. data/lib/linked_rails/model/tables.rb +26 -0
  92. data/lib/linked_rails/model.rb +13 -5
  93. data/lib/linked_rails/params_parser.rb +131 -55
  94. data/lib/linked_rails/policy/attribute_conditions.rb +2 -2
  95. data/lib/linked_rails/policy.rb +24 -17
  96. data/lib/linked_rails/rdf_error.rb +2 -2
  97. data/lib/linked_rails/routes.rb +37 -22
  98. data/lib/linked_rails/serializer/actionable.rb +27 -0
  99. data/lib/linked_rails/serializer/menuable.rb +31 -0
  100. data/lib/linked_rails/serializer/singularable.rb +26 -0
  101. data/lib/linked_rails/serializer.rb +23 -10
  102. data/lib/linked_rails/test_methods.rb +114 -0
  103. data/lib/linked_rails/translate.rb +19 -9
  104. data/lib/linked_rails/uri_template.rb +30 -0
  105. data/lib/linked_rails/version.rb +1 -1
  106. data/lib/linked_rails/vocab.rb +8 -0
  107. data/lib/linked_rails.rb +25 -12
  108. data/lib/rails/welcome_controller.rb +3 -3
  109. data/lib/rdf/query_fix.rb +15 -0
  110. metadata +22 -25
  111. data/app/models/linked_rails/actions/default_actions/create.rb +0 -60
  112. data/app/models/linked_rails/actions/default_actions/destroy.rb +0 -45
  113. data/app/models/linked_rails/actions/default_actions/update.rb +0 -50
  114. data/app/models/linked_rails/actions/default_actions.rb +0 -17
  115. data/lib/generators/linked_rails/install/templates/application_action_list.rb +0 -3
  116. data/lib/generators/linked_rails/model/templates/action_list.rb.tt +0 -6
  117. data/lib/linked_rails/enhancements/actionable/model.rb +0 -71
  118. data/lib/linked_rails/enhancements/actionable/serializer.rb +0 -25
  119. data/lib/linked_rails/enhancements/creatable/action.rb +0 -15
  120. data/lib/linked_rails/enhancements/destroyable/action.rb +0 -15
  121. data/lib/linked_rails/enhancements/destroyable/routing.rb +0 -19
  122. data/lib/linked_rails/enhancements/indexable/model.rb +0 -10
  123. data/lib/linked_rails/enhancements/menuable/model.rb +0 -36
  124. data/lib/linked_rails/enhancements/menuable/serializer.rb +0 -33
  125. data/lib/linked_rails/enhancements/route_concerns.rb +0 -56
  126. data/lib/linked_rails/enhancements/singularable/controller.rb +0 -43
  127. data/lib/linked_rails/enhancements/singularable/model.rb +0 -47
  128. data/lib/linked_rails/enhancements/singularable/serializer.rb +0 -28
  129. data/lib/linked_rails/enhancements/tableable/model.rb +0 -28
  130. data/lib/linked_rails/enhancements/updatable/action.rb +0 -15
  131. data/lib/linked_rails/enhancements/updatable/routing.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6779d430183378aeebf11d84973275d9f95ba6be8d9d806c4488f9c5e0a7ca11
4
- data.tar.gz: e98856daaf5f8698922faeec141b6f24c3e72856076955bd2892b067e37609d2
3
+ metadata.gz: eefab6e5626896f0baa3510637edc5b59d3e8aaf3e6b9b83f833e5f7f493ab86
4
+ data.tar.gz: be557fc4729209e7a3f5bc53cce009c6efd3291c0c4a1d0229b10ca12b30e184
5
5
  SHA512:
6
- metadata.gz: 17934ce95f375a4b36a63b56285f1db4e2171d6d1c5bc2747dc0132548b77c36a484be64aeacb47ec89fe15ba77fd39a9f44ee25096759438aea8882b8ec8dbf
7
- data.tar.gz: 30fff5ebacf094fcaada45caab3d15537ba5806692f9dd887f509155420880b07283ec41aa6282e2d572e15fcb7cdce508bd55d102bd790eb1b7be5cc1d353dd
6
+ metadata.gz: b0ad47f2cf9c64002e625593a678f54e751618420bba68fcb784b61469b7c043fa99eea38a957274d02e1eaae0968a21127752050308cadffda261b5a7bc8bf4
7
+ data.tar.gz: 0c7c4ad8099fd399370ac1c42673a65be720093df2e8f205d5cbc7a5383967d09f5fadd5ec87bf8d183984400b59208def613b161f65543ff9eabd938039d4f0
@@ -30,12 +30,12 @@ module LinkedRails
30
30
  @authorized_resources ||=
31
31
  params
32
32
  .require(:resources)
33
- .map { |param| param.permit(:include, :iri) }
33
+ .map { |param| resource_params(param) }
34
34
  .map(&method(:timed_authorized_resource))
35
35
  end
36
36
 
37
37
  def handle_resource_error(opts, error)
38
- log_resource_error(error)
38
+ log_resource_error(error, opts[:iri])
39
39
  status = error_status(error)
40
40
  body = error_body(status, error, opts[:iri]) if opts[:include].to_s == 'true'
41
41
 
@@ -50,7 +50,7 @@ module LinkedRails
50
50
  resource_body(error_resource(status, error, iri))
51
51
  end
52
52
 
53
- def log_resource_error(error)
53
+ def log_resource_error(error, _iri)
54
54
  return unless log_resource_error?(error)
55
55
 
56
56
  Rails.logger.error(error)
@@ -83,6 +83,12 @@ module LinkedRails
83
83
  RDF::Serializers.serializer_for(resource).new(resource, serializer_options).send(:render_hndjson)
84
84
  end
85
85
 
86
+ def resource_params(param)
87
+ params = param.permit(:include, :iri)
88
+ params[:iri] = URI(params[:iri])
89
+ params
90
+ end
91
+
86
92
  def resource_response_body(iri, rack_body, status)
87
93
  return rack_body.body if rack_body.is_a?(ActionDispatch::Response::RackBody)
88
94
 
@@ -134,16 +140,30 @@ module LinkedRails
134
140
 
135
141
  def term_from_vocab(iri)
136
142
  vocab = Vocab.for(iri)
137
- tag = iri.split(vocab.to_s).last
143
+ tag = iri.to_s.split(vocab.to_s).last
138
144
  vocab[tag]
139
145
  rescue NoMethodError
140
146
  nil
141
147
  end
142
148
 
149
+ def ontology_class(iri)
150
+ klass = LinkedRails.linked_models.detect do |model|
151
+ (model.iri.is_a?(Array) ? model.iri : [model.iri]).include?(iri)
152
+ end
153
+ LinkedRails.ontology_class_class.new(iri: iri, klass: klass)
154
+ end
155
+
156
+ def ontology_property(iri)
157
+ LinkedRails.ontology_property_class.new(iri: iri)
158
+ end
159
+
143
160
  def ontology_term_response(iri, term, include)
161
+ capital = term.relativize(term.vocab).to_s[0] =~ /[A-Z]/
162
+ resource = capital ? ontology_class(term) : ontology_property(term)
163
+
144
164
  resource_response(
145
165
  iri,
146
- body: include ? resource_body(LinkedRails.ontology_property_class.new(iri: term)) : nil,
166
+ body: include ? resource_body(resource) : nil,
147
167
  cache: :public,
148
168
  language: I18n.locale,
149
169
  status: 200
@@ -189,7 +209,7 @@ module LinkedRails
189
209
  end
190
210
 
191
211
  def wrong_host?(iri)
192
- !iri.starts_with?(LinkedRails.iri)
212
+ !iri.to_s.starts_with?(LinkedRails.iri)
193
213
  end
194
214
  end
195
215
  end
@@ -3,47 +3,5 @@
3
3
  module LinkedRails
4
4
  class EnumValuesController < LinkedRails.controller_parent_class
5
5
  active_response :index
6
-
7
- private
8
-
9
- def enum_options!
10
- serializer_class!.enum_options(params[:attribute]) || raise(ActiveRecord::RecordNotFound)
11
- end
12
-
13
- def requested_resource
14
- return super unless action_name == 'index'
15
-
16
- @requested_resource ||= LinkedRails::Sequence.new(
17
- enum_options!.values,
18
- id: index_iri,
19
- scope: LinkedRails::EnumValuePolicy::Scope
20
- )
21
- end
22
-
23
- def model_class
24
- @model_class ||= self.class.linked_models.detect do |klass|
25
- klass.to_s == ([params[:module]].compact + [params[:klass]&.singularize]).join('/').classify
26
- end
27
- end
28
-
29
- def model_class!
30
- model_class || raise(ActiveRecord::RecordNotFound)
31
- end
32
-
33
- def serializer_class
34
- @serializer_class ||= RDF::Serializers.serializer_for(model_class!)
35
- end
36
-
37
- def serializer_class!
38
- serializer_class || raise(ActiveRecord::RecordNotFound)
39
- end
40
-
41
- class << self
42
- def linked_models
43
- @linked_models ||= ObjectSpace.each_object(Class).select do |c|
44
- c.included_modules.include?(LinkedRails::Model)
45
- end
46
- end
47
- end
48
6
  end
49
7
  end
@@ -7,15 +7,23 @@ module LinkedRails
7
7
  class Item # rubocop:disable Metrics/ClassLength
8
8
  include ActiveModel::Model
9
9
  include LinkedRails::Model
10
- enhance LinkedRails::Enhancements::Singularable
11
10
 
12
- attr_accessor :list, :policy_arguments, :submit_label
11
+ attr_accessor :inherit, :list, :one_click, :policy_arguments, :submit_label, :target_path
13
12
  attr_writer :parent, :resource, :root_relative_iri, :user_context, :object,
14
13
  :target
15
14
  delegate :user_context, to: :list, allow_nil: true
16
-
17
- %i[description result type policy label image url include_object include_paths collection condition form completed
18
- tag http_method favorite path policy_resource predicate resource].each do |method|
15
+ collection_options(
16
+ association_base: lambda {
17
+ action_list = parent ? parent.action_list(user_context) : association_class.app_action_list(user_context)
18
+
19
+ action_list.actions
20
+ },
21
+ display: :grid,
22
+ title: -> { I18n.t('actions.plural') }
23
+ )
24
+
25
+ %i[condition description result type policy label image target_url collection form
26
+ tag http_method favorite action_path policy_resource predicate resource].each do |method|
19
27
  attr_writer method
20
28
  define_method method do
21
29
  var = instance_variable_get(:"@#{method}")
@@ -28,10 +36,10 @@ module LinkedRails
28
36
 
29
37
  def action_status
30
38
  @action_status ||=
31
- if completed
32
- Vocab.schema.CompletedActionStatus
33
- elsif policy_valid?
39
+ if policy_valid?
34
40
  Vocab.schema.PotentialActionStatus
41
+ elsif policy_status
42
+ policy_status
35
43
  elsif policy_expired?
36
44
  Vocab.ontola[:ExpiredActionStatus]
37
45
  else
@@ -39,13 +47,11 @@ module LinkedRails
39
47
  end
40
48
  end
41
49
 
42
- def as_json(_opts = {})
50
+ def as_json(**_opts)
43
51
  {}
44
52
  end
45
53
 
46
54
  def available?
47
- return false unless action_status == Vocab.schema.PotentialActionStatus
48
-
49
55
  @condition.nil? || condition
50
56
  end
51
57
 
@@ -62,9 +68,8 @@ module LinkedRails
62
68
  I18n.t("actions.status.#{action_status.to_s.split('#').last}", default: nil)
63
69
  end
64
70
 
65
- def form_resource_includes # rubocop:disable Metrics/CyclomaticComplexity
71
+ def form_resource_includes
66
72
  return {} if included_object.nil?
67
- return include_paths || {} if iri.anonymous?
68
73
 
69
74
  includes = included_object.class.try(:preview_includes)&.presence || []
70
75
 
@@ -72,7 +77,7 @@ module LinkedRails
72
77
  end
73
78
 
74
79
  def included_object
75
- object if include_object || object&.iri&.anonymous?
80
+ object if object&.iri&.anonymous?
76
81
  end
77
82
 
78
83
  def object
@@ -92,10 +97,10 @@ module LinkedRails
92
97
  end
93
98
 
94
99
  def policy_message
95
- resource_policy.try(:message) if action_status == Vocab.ontola[:DisabledActionStatus]
100
+ resource_policy.try(:message) unless policy_valid?
96
101
  end
97
102
 
98
- def root_relative_iri(_opts = {})
103
+ def root_relative_iri(**_opts)
99
104
  value = root_relative_iri_from_var
100
105
  value = RDF::URI(value) unless value.blank? || value.is_a?(RDF::URI)
101
106
  return @root_relative_iri = value if value
@@ -117,16 +122,26 @@ module LinkedRails
117
122
  resource.try(:singular_resource?)
118
123
  end
119
124
 
125
+ def policy_status
126
+ resource_policy.try(:action_status)
127
+ end
128
+
120
129
  def iri_opts
121
- resource&.iri_opts || {}
130
+ return {} if resource.blank?
131
+
132
+ resource.try(:singular_resource?) ? resource.singular_iri_opts : resource.iri_opts
122
133
  end
123
134
 
124
135
  def iri_template
125
- path_suffix = path.blank? ? "/actions/#{tag}" : "/#{path}"
136
+ path_suffix = "/#{action_path || tag}"
126
137
 
127
- return @iri_template ||= URITemplate.new(path_suffix) if resource.blank?
138
+ return @iri_template ||= LinkedRails::URITemplate.new(path_suffix) if resource.blank?
128
139
 
129
- @iri_template ||= iri_template_expand_path(resource.send(:iri_template), path_suffix)
140
+ base_template = resource.send(resource.try(:singular_resource?) ? :singular_iri_template : :iri_template)
141
+ @iri_template ||= iri_template_expand_path(
142
+ base_template.to_s.sub('display,', '').sub('sort%5B%5D*,', ''),
143
+ path_suffix
144
+ )
130
145
  end
131
146
 
132
147
  def rdf_type
@@ -184,6 +199,12 @@ module LinkedRails
184
199
  @root_relative_iri
185
200
  end
186
201
 
202
+ def target_url_fallback
203
+ base = (resource.try(:singular_resource?) ? resource.singular_iri : resource.iri).dup
204
+ base.path += "/#{target_path}" if target_path.present?
205
+ base
206
+ end
207
+
187
208
  def type_fallback
188
209
  Vocab.schema.UpdateAction
189
210
  end
@@ -203,23 +224,18 @@ module LinkedRails
203
224
  end
204
225
 
205
226
  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)
227
+ parent = parent_from_params!(params, user_context) if params.key?(:parent_iri)
208
228
 
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]
229
+ default_collection_option(:collection_class).collection_or_view(
230
+ default_collection_options.merge(parent: parent),
231
+ index_collection_params(params, user_context)
216
232
  )
217
233
  end
218
234
 
219
235
  def requested_single_resource(params, user_context)
220
236
  return nil if params[:id].blank?
221
237
 
222
- parent = parent_from_params(params, user_context)
238
+ parent = parent_from_params!(params, user_context) if params.key?(:parent_iri)
223
239
  action_list = parent ? parent.action_list(user_context) : app_action_list(user_context)
224
240
 
225
241
  action_list&.action(params[:id].to_sym)
@@ -7,14 +7,12 @@ module LinkedRails
7
7
  class List
8
8
  include ActiveModel::Model
9
9
  include LinkedRails::Model
10
- include DefaultActions
11
- extend LinkedRails::Enhanceable
12
10
 
13
11
  attr_accessor :resource, :user_context
14
12
  class_attribute :_defined_actions, instance_reader: false, instance_writer: false
15
13
 
16
14
  def actions
17
- @actions ||= defined_actions.map { |tag, opts| action_item(tag, opts.dup) }
15
+ @actions ||= defined_actions.map { |tag, opts| action_item(tag, opts.dup) }.select(&:available?)
18
16
  end
19
17
 
20
18
  def action(tag)
@@ -34,9 +32,9 @@ module LinkedRails
34
32
  private
35
33
 
36
34
  def action_item(tag, options)
37
- options[:tag] ||= options[:action_tag] || tag
35
+ options[:tag] ||= tag
38
36
  options[:list] ||= self
39
- LinkedRails.actions_item_class.new(options.except(:action_tag))
37
+ LinkedRails.actions_item_class.new(options.except(:action_name))
40
38
  end
41
39
 
42
40
  def association
@@ -77,26 +75,11 @@ module LinkedRails
77
75
 
78
76
  private
79
77
 
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
78
  def initial_defined_actions(clone_from = {})
96
79
  {
97
- collection: clone_from[:collection].dup || {},
98
- resource: clone_from[:resource].dup || {},
99
- singular: clone_from[:singular].dup || {}
80
+ collection: clone_from[:collection].dup&.select { |_, value| value[:inherit] != false } || {},
81
+ resource: clone_from[:resource].dup&.select { |_, value| value[:inherit] != false } || {},
82
+ singular: clone_from[:singular].dup&.select { |_, value| value[:inherit] != false } || {}
100
83
  }
101
84
  end
102
85
 
@@ -106,8 +89,6 @@ module LinkedRails
106
89
  self._defined_actions = initial_defined_actions(superclass.try(:_defined_actions) || {})
107
90
  end
108
91
  end
109
-
110
- enhanceable :actionable_class, :Action
111
92
  end
112
93
  end
113
94
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class Collection
5
+ module Configuration
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ private
10
+
11
+ def define_default_option_method(option)
12
+ attr_accessor "default_#{option}"
13
+ end
14
+
15
+ def define_getter_option_method(option)
16
+ attr_writer option
17
+
18
+ define_method(option) do
19
+ resolve_collection_option(option)
20
+ end
21
+ end
22
+ end
23
+
24
+ included do
25
+ attr_accessor :iri_template
26
+
27
+ LinkedRails::Model::Collections::COLLECTION_CUSTOMIZABLE_OPTIONS.each_key do |option|
28
+ define_default_option_method(option)
29
+ end
30
+ LinkedRails::Model::Collections::COLLECTION_OPTIONS.each_key do |option|
31
+ define_getter_option_method(option)
32
+ end
33
+
34
+ def display
35
+ resolve_collection_option(:display)&.to_sym
36
+ end
37
+
38
+ def type
39
+ resolve_collection_option(:type)&.to_sym
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def resolve_collection_option(option)
46
+ var_name = :"@#{option}"
47
+ default_method_name = "default_#{option}"
48
+
49
+ var = instance_variable_defined?(var_name) ? instance_variable_get(var_name) : try(default_method_name)
50
+
51
+ var.respond_to?(:call) ? instance_exec(&var) : var
52
+ end
53
+ end
54
+ end
55
+ end
@@ -8,7 +8,7 @@ module LinkedRails
8
8
 
9
9
  attr_accessor :default_filter, :key, :value, :collection
10
10
 
11
- def iri(_opts = {})
11
+ def iri(**_opts)
12
12
  self
13
13
  end
14
14
  end
@@ -13,7 +13,7 @@ module LinkedRails
13
13
  callable_variable(:options_array)
14
14
  callable_variable(:options_in)
15
15
 
16
- def iri(_opts = {})
16
+ def iri(**_opts)
17
17
  self
18
18
  end
19
19
 
@@ -25,6 +25,10 @@ module LinkedRails
25
25
  attrs = option.is_a?(Hash) ? option : {value: option}
26
26
  Collection::FilterOption.new(attrs.merge(collection: collection, key: key))
27
27
  end
28
+
29
+ def serializable?
30
+ options_in || options_array
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -9,7 +9,7 @@ module LinkedRails
9
9
 
10
10
  attr_accessor :collection, :count, :value, :key
11
11
 
12
- def iri(_opts = {})
12
+ def iri(**_opts)
13
13
  self
14
14
  end
15
15
  end
@@ -5,12 +5,7 @@ module LinkedRails
5
5
  module Filterable
6
6
  include RDF::Serializers::DataTypeHelper
7
7
 
8
- attr_writer :default_filters, :filter, :unfiltered_collection
9
-
10
- def default_filters
11
- opts = @default_filters || association_class.try(:default_filters) || {}
12
- opts.respond_to?(:call) ? opts.call(parent) : opts
13
- end
8
+ attr_writer :filter, :unfiltered_collection
14
9
 
15
10
  def filter
16
11
  default_filters.merge(@filter || {})
@@ -19,7 +14,7 @@ module LinkedRails
19
14
  delegate :filter_options, to: :association_class
20
15
 
21
16
  def filter_fields
22
- @filter_fields ||= filter_options&.map { |key, options| filter_field(key, options) }
17
+ @filter_fields ||= filter_options&.map { |key, options| filter_field(key, options) }&.select(&:serializable?)
23
18
  end
24
19
 
25
20
  def filtered?
@@ -83,7 +78,7 @@ module LinkedRails
83
78
 
84
79
  def sanitized_filter_value(key, value)
85
80
  mapping = association_class.predicate_mapping[key]
86
- datatype = mapping.is_a?(FastJsonapi::Relationship) ? RDF.xsd.anyURI : mapping.datatype
81
+ datatype = mapping.is_a?(FastJsonapi::Relationship) ? Vocab.xsd.anyURI : mapping.datatype
87
82
  val = xsd_to_rdf(datatype, value)
88
83
  val.literal? ? val.object : val
89
84
  end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class Collection
5
+ module Infinite
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ attr_accessor :before
10
+ end
11
+
12
+ def initialize(orignial = {})
13
+ attrs = orignial.with_indifferent_access
14
+ attrs[:before] = attrs[:before]&.map { |val| val.with_indifferent_access }
15
+ super(attrs)
16
+ end
17
+
18
+ def next
19
+ return if before.blank? || members.blank?
20
+
21
+ current_opts = {
22
+ collection: collection,
23
+ filter: filter
24
+ }
25
+ next_view = collection.view_with_opts(current_opts.merge(before: next_before_values))
26
+
27
+ next_view.iri if next_view.count.positive?
28
+ end
29
+
30
+ def prev; end
31
+
32
+ def type
33
+ :infinite
34
+ end
35
+
36
+ private
37
+
38
+ def additional_statements(arel, index)
39
+ (preconditions(index) + [arel]).reduce { |or_acc, or_value| or_acc.and(or_value) }
40
+ end
41
+
42
+ def before_iri_opts
43
+ before&.map { |hash| "#{CGI.escape(hash[:key])}=#{hash[:value]}" }
44
+ end
45
+
46
+ def before_query
47
+ before_values.each_with_index.reduce(nil) do |acc, (value, index)|
48
+ arel = arel_table[value[:attribute]].send(value[:direction], value[:value])
49
+ acc.nil? ? arel : acc.or(additional_statements(arel, index))
50
+ end
51
+ end
52
+
53
+ def before_values
54
+ @before_values ||= before&.map do |value|
55
+ sorting = collection.sortings.detect { |s| s.key == value[:key] }
56
+ {
57
+ attribute: sorting.attribute_name,
58
+ direction: sorting.sort_direction,
59
+ key: value[:key],
60
+ value: value[:value]
61
+ }
62
+ end
63
+ end
64
+
65
+ def iri_opts
66
+ {
67
+ 'before%5B%5D': before_iri_opts
68
+ }.merge(collection.iri_opts)
69
+ end
70
+
71
+ def members_query
72
+ prepare_members(association_base)
73
+ .where(before_query)
74
+ .limit(page_size)
75
+ end
76
+
77
+ def next_before_values
78
+ last_record = members.last
79
+ before_values.map do |val|
80
+ value = last_record.send(val[:attribute])
81
+ value = value.utc.iso8601(6) if value.is_a?(Time)
82
+ {
83
+ key: val[:key],
84
+ value: value
85
+ }
86
+ end
87
+ end
88
+
89
+ def preconditions(index)
90
+ before_values[0...index].map do |v|
91
+ condition = arel_table[v[:attribute]].eq(v[:value])
92
+ condition = condition.or(arel_table[v[:attribute]].eq(nil)) if v[:direction] == :gt
93
+ condition
94
+ end
95
+ end
96
+
97
+ def sort_column
98
+ @sort_column ||= collection.sortings.last.sort_value.keys.first
99
+ end
100
+ end
101
+ end
102
+ end
@@ -3,96 +3,7 @@
3
3
  module LinkedRails
4
4
  class Collection
5
5
  class InfiniteView < LinkedRails.collection_view_class
6
- attr_accessor :before
7
-
8
- def initialize(orignial = {})
9
- attrs = orignial.with_indifferent_access
10
- attrs[:before] = attrs[:before]&.map { |val| val.with_indifferent_access }
11
- super(attrs)
12
- end
13
-
14
- def next
15
- return if before.blank? || members.blank?
16
-
17
- current_opts = {
18
- collection: collection,
19
- filter: filter
20
- }
21
- next_view = collection.view_with_opts(current_opts.merge(before: next_before_values))
22
-
23
- next_view.iri if next_view.count.positive?
24
- end
25
-
26
- def prev; end
27
-
28
- def type
29
- :infinite
30
- end
31
-
32
- private
33
-
34
- def additional_statements(arel, index)
35
- (preconditions(index) + [arel]).reduce { |or_acc, or_value| or_acc.and(or_value) }
36
- end
37
-
38
- def before_iri_opts
39
- before&.map { |hash| "#{CGI.escape(hash[:key])}=#{hash[:value]}" }
40
- end
41
-
42
- def before_query
43
- before_values.each_with_index.reduce(nil) do |acc, (value, index)|
44
- arel = arel_table[value[:attribute]].send(value[:direction], value[:value])
45
- acc.nil? ? arel : acc.or(additional_statements(arel, index))
46
- end
47
- end
48
-
49
- def before_values
50
- @before_values ||= before&.map do |value|
51
- sorting = collection.sortings.detect { |s| s.key == value[:key] }
52
- {
53
- attribute: sorting.attribute_name,
54
- direction: sorting.sort_direction,
55
- key: value[:key],
56
- value: value[:value]
57
- }
58
- end
59
- end
60
-
61
- def iri_opts
62
- {
63
- 'before%5B%5D': before_iri_opts
64
- }.merge(collection.iri_opts)
65
- end
66
-
67
- def members_query
68
- prepare_members(association_base)
69
- .where(before_query)
70
- .limit(page_size)
71
- end
72
-
73
- def next_before_values
74
- last_record = members.last
75
- before_values.map do |val|
76
- value = last_record.send(val[:attribute])
77
- value = value.utc.iso8601(6) if value.is_a?(Time)
78
- {
79
- key: val[:key],
80
- value: value
81
- }
82
- end
83
- end
84
-
85
- def preconditions(index)
86
- before_values[0...index].map do |v|
87
- condition = arel_table[v[:attribute]].eq(v[:value])
88
- condition = condition.or(arel_table[v[:attribute]].eq(nil)) if v[:direction] == :gt
89
- condition
90
- end
91
- end
92
-
93
- def sort_column
94
- @sort_column ||= collection.sortings.last.sort_value.keys.first
95
- end
6
+ include LinkedRails::Collection::Infinite
96
7
  end
97
8
  end
98
9
  end