linked_rails 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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