abstractor 4.3.3 → 4.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2a061d566e99d4c51eb64e933e20c1a87d8055fa
4
- data.tar.gz: 3c110a04810414ee724e1ecfffdc05f907723da4
3
+ metadata.gz: b812a802ae7263947c7d57b0e8ebd3bfc5d9861d
4
+ data.tar.gz: 7f950eef0cc2ebfb940219b9f3fdb6f83853cb51
5
5
  SHA512:
6
- metadata.gz: 5f5ebb7723d60f1389bce4c4f9a23aea5ac6f7982079014f0c5869fef4657f46a6e90b62730806159737b4459b95caa9ed3d4f1d27ade32fd023f80c218331d6
7
- data.tar.gz: fe161176c8a8570a50a6d24e2a43326cef54f3a602844ca9934bcb74b3044225d778df84a1cc523a3b017e5e22d11ea465fa669b23c3b5b2dadb4156062a01d6
6
+ metadata.gz: 5c5b88efd3f276b9bb8b77f5a800c0b44474f9ce2b67d66795e8a8390e40643ee155ed47d41f1777892f6bfef62a75262f70808108e095326e48e876e9de68b0
7
+ data.tar.gz: e2e6bec4bace81fd45b51de2f085ddd6d780ade29976f9cd4b9c4c1530b70af9780e5ee9b8d9d0678852ddd2621981c06e046e045728ba8aab98b980abc72fa1
@@ -16,14 +16,14 @@
16
16
  - when 'number'
17
17
  = f.number_field :value
18
18
  - when 'radio button list'
19
- - values = abstraction_schema.abstractor_object_values.sort_by(&:value)
19
+ - values = abstraction_schema.abstractor_object_values.order('abstractor_abstraction_schema_object_values.display_order, abstractor_object_values.value')
20
20
  - values.each do |value|
21
21
  = f.radio_button :value, value.value
22
22
  = f.label :value, value.value, value: value.value
23
23
  = f.radio_button :value, '', {:style => 'display:none;' }
24
24
   
25
25
  - when 'list'
26
- - values = abstraction_schema.abstractor_object_values.sort_by(&:value)
26
+ - values = abstraction_schema.abstractor_object_values.order('abstractor_abstraction_schema_object_values.display_order, abstractor_object_values.value')
27
27
  = f.select :value, values.map{|s| [s.value, s.value]}, {:include_blank => true}, :class => "combobox"
28
28
  - when 'dynamic list'
29
29
  - values = abstractor_abstraction.about.send(abstractor_abstraction.abstractor_subject.dynamic_list_method).sort_by { |l| l[:value] }
@@ -0,0 +1,5 @@
1
+ class AddDisplayOrderToAbstractorAbstractionSchemaObjectValues < ActiveRecord::Migration
2
+ def change
3
+ add_column :abstractor_abstraction_schema_object_values, :display_order, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddSubtypeToAbstractorSubjectGroups < ActiveRecord::Migration
2
+ def change
3
+ add_column :abstractor_subject_groups, :subtype, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddSubtypeToAbstractorAbstractionGroups < ActiveRecord::Migration
2
+ def change
3
+ add_column :abstractor_abstraction_groups, :subtype, :string
4
+ end
5
+ end
@@ -88,9 +88,12 @@ module Abstractor
88
88
  # @return [void]
89
89
  def abstract(options = {})
90
90
  options = { namespace_type: nil, namespace_id: nil, abstractor_abstraction_schema_ids: [] }.merge(options)
91
+ sentinental_groups = []
91
92
  self.class.abstractor_subjects(options).each do |abstractor_subject|
92
93
  abstractor_subject.abstract(self)
94
+ sentinental_groups << abstractor_subject.abstractor_subject_group if abstractor_subject.abstractor_subject_group && abstractor_subject.abstractor_subject_group.has_subtype?(Abstractor::Enum::ABSTRACTOR_GROUP_SENTINENTAL_SUBTYPE)
93
95
  end
96
+ sentinental_groups.uniq.map{|sentinental_group| regroup_sentinental_suggestions(sentinental_group, options)}
94
97
  end
95
98
 
96
99
  def detect_abstractor_abstraction(abstractor_subject)
@@ -98,11 +101,13 @@ module Abstractor
98
101
  end
99
102
 
100
103
  def find_or_create_abstractor_abstraction(abstractor_abstraction_schema, abstractor_subject)
104
+ options = { namespace_type: abstractor_subject.namespace_type, namespace_id: abstractor_subject.namespace_id }
101
105
  if abstractor_abstraction = detect_abstractor_abstraction(abstractor_subject)
102
106
  else
103
107
  abstractor_abstraction = Abstractor::AbstractorAbstraction.create!(abstractor_subject: abstractor_subject, about: self)
108
+
104
109
  if abstractor_subject.groupable?
105
- abstractor_abstraction_group = find_or_initialize_abstractor_abstraction_group(abstractor_subject.abstractor_subject_group)
110
+ abstractor_abstraction_group = find_or_initialize_abstractor_abstraction_group(abstractor_subject.abstractor_subject_group, options)
106
111
  abstractor_abstraction_group.abstractor_abstractions << abstractor_abstraction
107
112
  abstractor_abstraction_group.save!
108
113
  end
@@ -110,12 +115,15 @@ module Abstractor
110
115
  abstractor_abstraction
111
116
  end
112
117
 
113
- def detect_abstractor_abstraction_group(abstractor_subject_group)
114
- abstractor_abstraction_groups(true).detect { |abstractor_abstraction_group| abstractor_abstraction_group.abstractor_subject_group_id == abstractor_subject_group.id }
118
+ def detect_abstractor_abstraction_group(abstractor_subject_group, options)
119
+ abstractor_abstraction_groups(true).
120
+ select { |abstractor_abstraction_group| abstractor_abstraction_group.abstractor_subject_group_id == abstractor_subject_group.id }.
121
+ select { |abstractor_abstraction_group| abstractor_abstraction_group.abstractor_abstractions.joins(:abstractor_subject).where(abstractor_subjects: { namespace_type: options[:namespace_type], namespace_id: options[:namespace_id]}).any?}.
122
+ first
115
123
  end
116
124
 
117
- def find_or_initialize_abstractor_abstraction_group(abstractor_subject_group)
118
- if abstractor_abstraction_group = detect_abstractor_abstraction_group(abstractor_subject_group)
125
+ def find_or_initialize_abstractor_abstraction_group(abstractor_subject_group, options)
126
+ if abstractor_abstraction_group = detect_abstractor_abstraction_group(abstractor_subject_group, options)
119
127
  else
120
128
  abstractor_abstraction_group = Abstractor::AbstractorAbstractionGroup.new(abstractor_subject_group: abstractor_subject_group, about: self, system_generated: true)
121
129
  end
@@ -191,6 +199,143 @@ module Abstractor
191
199
  end
192
200
  end
193
201
  end
202
+
203
+ ##
204
+ # Regroups suggestions for subjects grouped marked with 'sentinental' subtype. Does not affect abstraction groups with curated values.
205
+ # Creates an abstraction group for each combination of suggestions that came from the same sentence.
206
+ # Creates groups only if there are enough abstractions.
207
+ #
208
+ # @param [ActiveRecord::Relation] sentinental_group sentinental group to process
209
+ # @return [void]
210
+ def regroup_sentinental_suggestions(sentinental_group, options)
211
+ sentinental_group_abstractor_subjects = sentinental_group.abstractor_subjects.not_deleted
212
+ if options[:namespace_type] || options[:namespace_id]
213
+ sentinental_group_abstractor_subjects = sentinental_group_abstractor_subjects.where(namespace_type: options[:namespace_type], namespace_id: options[:namespace_id])
214
+ end
215
+
216
+ sentinental_group_abstractor_abstraction_groups = Abstractor::AbstractorAbstractionGroup.not_deleted.joins(:abstractor_subject_group, :abstractor_abstractions).where(abstractor_subject_group_id: sentinental_group.id, abstractor_abstractions: {about_id: self.id, abstractor_subject_id: sentinental_group_abstractor_subjects.map(&:id)}).distinct
217
+
218
+ sentinental_group_abstractor_suggestion_sources = Abstractor::AbstractorSuggestionSource.joins(abstractor_suggestion: { abstractor_abstraction: :abstractor_abstraction_group})
219
+ .where(abstractor_abstraction_groups: { id: sentinental_group_abstractor_abstraction_groups.map(&:id)}, abstractor_abstractions: { abstractor_subject_id: sentinental_group_abstractor_subjects.map(&:id), about_id: self.id})
220
+
221
+ sentinental_abstractor_abstraction_groups = sentinental_group_abstractor_abstraction_groups.where(subtype: Abstractor::Enum::ABSTRACTOR_GROUP_SENTINENTAL_SUBTYPE)
222
+
223
+ sentinental_group_abstractor_abstraction_groups.each do |abstractor_abstraction_group|
224
+ unless abstractor_abstraction_group.abstractor_abstractions.not_deleted.where(about_id: self.id).where('value is not null').any? # skip abstraction groups with curated abstractions
225
+ # get all suggestion sources
226
+ abstractor_suggestion_sources = sentinental_group_abstractor_suggestion_sources.where(abstractor_abstraction_groups: { id: abstractor_abstraction_group.id})
227
+
228
+ # get all matched sentences
229
+ sentence_match_values = abstractor_suggestion_sources.select(:sentence_match_value).distinct.map(&:sentence_match_value).compact
230
+
231
+ # skip groups where all abstractions come from the same sentence
232
+ unless sentence_match_values.length == 1
233
+ # create abstraction group for each sentence
234
+ sentence_match_values.each do |sentence_match_value|
235
+ # get all suggestion sources that reference the sentence
236
+ abstractor_suggestion_sources_by_sentence = abstractor_suggestion_sources.where(sentence_match_value: sentence_match_value)
237
+
238
+ abstractor_subjects = abstractor_suggestion_sources_by_sentence.
239
+ map{|abstractor_suggestion_source| abstractor_suggestion_source.abstractor_suggestion.abstractor_abstraction.abstractor_subject }.
240
+ reject{|abstractor_subject| abstractor_subject.abstractor_subject_group.blank? || abstractor_subject.abstractor_subject_group.id != sentinental_group.id}.uniq
241
+
242
+ if abstractor_subjects.length == sentinental_group_abstractor_subjects.length
243
+ matching_abstractor_suggestion_sources = sentinental_group_abstractor_suggestion_sources.where(sentence_match_value: sentence_match_value)
244
+
245
+ existing_abstractor_abstraction_group = matching_abstractor_suggestion_sources.
246
+ map{|abstractor_suggestion_source| abstractor_suggestion_source.abstractor_suggestion.abstractor_abstraction.abstractor_abstraction_group}.
247
+ select{|aag| sentinental_abstractor_abstraction_groups.map(&:id).include? aag.id}.
248
+ reject{|aag| aag.id == abstractor_abstraction_group.id}.uniq.first
249
+
250
+ if existing_abstractor_abstraction_group
251
+ new_abstractor_abstraction_group = existing_abstractor_abstraction_group
252
+ else
253
+ new_abstractor_abstraction_group = Abstractor::AbstractorAbstractionGroup.new(abstractor_subject_group: abstractor_abstraction_group.abstractor_subject_group, about: self, system_generated: true, subtype: abstractor_abstraction_group.abstractor_subject_group.subtype)
254
+ end
255
+
256
+ abstractor_suggestion_sources_by_sentence.all.each do |abstractor_suggestion_source|
257
+ abstractor_suggestion = abstractor_suggestion_source.abstractor_suggestion
258
+ abstractor_abstraction = abstractor_suggestion.abstractor_abstraction
259
+
260
+ # if corresponding abstraction has more than one suggestion and should not be moved
261
+ # create a new abstraction if the new group does not yet have abstraction for the same subject
262
+ abstractor_subject = abstractor_abstraction.abstractor_subject
263
+ existing_new_abstractor_abstraction = new_abstractor_abstraction_group.abstractor_abstractions.select{|aa| aa.abstractor_subject_id == abstractor_subject.id}.first
264
+
265
+ if existing_new_abstractor_abstraction
266
+ new_abstractor_abstraction = existing_new_abstractor_abstraction
267
+ else
268
+ if abstractor_abstraction.abstractor_suggestions.length > 1
269
+ new_abstractor_abstraction = Abstractor::AbstractorAbstraction.create!(abstractor_subject: abstractor_suggestion.abstractor_abstraction.abstractor_subject, about: self)
270
+ else
271
+ new_abstractor_abstraction = abstractor_abstraction
272
+ new_abstractor_abstraction.abstractor_abstraction_group_member = nil
273
+ new_abstractor_abstraction.build_abstractor_abstraction_group_member(abstractor_abstraction_group: new_abstractor_abstraction_group)
274
+ end
275
+ unless new_abstractor_abstraction_group.abstractor_abstractions.include? new_abstractor_abstraction
276
+ new_abstractor_abstraction_group.abstractor_abstractions << new_abstractor_abstraction
277
+ end
278
+ end
279
+
280
+ # if new abstraction already has matching suggestion, use it to map sources
281
+ new_abstractor_suggestion = new_abstractor_abstraction.detect_abstractor_suggestion(abstractor_suggestion.suggested_value, abstractor_suggestion.unknown, abstractor_suggestion.not_applicable)
282
+
283
+ # if matching suggestion does not exist, create a new suggestion if corresponding suggestion has multiple sources
284
+ # and should not be moved of move existing one to the new abstraction
285
+ # and map suggestion source to the new suggestion
286
+ if new_abstractor_suggestion.blank?
287
+ if abstractor_suggestion.abstractor_suggestion_sources.length > 1
288
+ new_abstractor_suggestion ||= Abstractor::AbstractorSuggestion.create!(
289
+ abstractor_abstraction: new_abstractor_abstraction,
290
+ abstractor_suggestion_status: Abstractor::AbstractorSuggestionStatus.where(name: 'Needs review').first,
291
+ suggested_value: abstractor_suggestion.suggested_value,
292
+ unknown: abstractor_suggestion.unknown,
293
+ not_applicable: abstractor_suggestion.not_applicable
294
+ )
295
+ else
296
+ new_abstractor_suggestion = abstractor_suggestion
297
+ end
298
+ end
299
+
300
+ new_abstractor_suggestion.abstractor_abstraction = new_abstractor_abstraction
301
+ new_abstractor_suggestion.save!
302
+
303
+ existing_abstractor_suggestion_source = abstractor_suggestion.detect_abstractor_suggestion_source(abstractor_suggestion_source.abstractor_abstraction_source, abstractor_suggestion_source.sentence_match_value, abstractor_suggestion_source.source_id, abstractor_suggestion_source.source_type, abstractor_suggestion_source.source_method, abstractor_suggestion_source.section_name)
304
+
305
+ if existing_abstractor_suggestion_source && existing_abstractor_suggestion_source != abstractor_suggestion_source
306
+ abstractor_suggestion_source.delete
307
+ else
308
+ abstractor_suggestion_source.abstractor_suggestion = new_abstractor_suggestion
309
+ abstractor_suggestion_source.save!
310
+ end
311
+ end
312
+
313
+ # do not save group if it does not have abstractions
314
+ new_abstractor_abstraction_group.save! if new_abstractor_abstraction_group.abstractor_abstractions.any?
315
+ end
316
+ end
317
+
318
+ abstractor_abstraction_group_siblings = AbstractorAbstractionGroup.not_deleted.joins(:abstractor_subject_group, :abstractor_abstractions).where(abstractor_subject_group_id: sentinental_group.id, abstractor_abstractions: {about_id: self.id, abstractor_subject_id: sentinental_group_abstractor_subjects.map(&:id)}).distinct
319
+
320
+ if abstractor_abstraction_group_siblings.length > 1
321
+ abstractor_abstraction_group.reload.abstractor_abstractions.each do |abstractor_abstraction|
322
+ abstractor_abstraction.abstractor_suggestions.each do |abstractor_suggestion|
323
+ abstractor_suggestion.abstractor_suggestion_sources.delete_all
324
+ abstractor_suggestion.abstractor_suggestion_object_value.delete if abstractor_suggestion.abstractor_suggestion_object_value
325
+ abstractor_suggestion.delete
326
+ end
327
+ abstractor_abstraction.abstractor_indirect_sources.each do |abstractor_indirect_source|
328
+ abstractor_indirect_source.delete
329
+ end
330
+ abstractor_abstraction.delete
331
+ end
332
+ abstractor_abstraction_group.reload.abstractor_abstraction_group_members.map{|a| a.delete}
333
+ abstractor_abstraction_group.delete
334
+ end
335
+ end
336
+ end
337
+ end
338
+ end
194
339
  end
195
340
 
196
341
  module ClassMethods
@@ -198,7 +343,7 @@ module Abstractor
198
343
  # Returns all abstractable entities filtered by the parameter abstractor_suggestion_type:
199
344
  #
200
345
  # * 'unknown': Filter abstractable entites having at least one suggestion withat a suggested value of 'unknown'
201
- # * 'not unknown': Filter abstractable entites having at least one suggestion with an acutal value
346
+ # * 'suggested': Filter abstractable entites having at least one suggestion with an acutal value
202
347
  #
203
348
  # @param [String] abstractor_suggestion_type Filter abstactable entities that have a least one 'unknwon' or at least one 'not unknown' suggestion
204
349
  # @param [Hash] options The options to filter the entities returned.
@@ -213,7 +358,7 @@ module Abstractor
213
358
  case abstractor_suggestion_type
214
359
  when Abstractor::Enum::ABSTRACTION_SUGGESTION_TYPE_UNKNOWN
215
360
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? AND sub.abstractor_abstraction_schema_id IN (?) JOIN abstractor_suggestions sug ON aa.id = sug.abstractor_abstraction_id WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND sug.unknown = ?)", options[:namespace_type], options[:namespace_id], options[:abstractor_abstraction_schemas], true])
216
- when Abstractor::Enum::ABSTRACTION_SUGGESTION_TYPE_NOT_UNKNOWN
361
+ when Abstractor::Enum::ABSTRACTION_SUGGESTION_TYPE_SUGGESTED
217
362
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? AND sub.abstractor_abstraction_schema_id IN (?) JOIN abstractor_suggestions sug ON aa.id = sug.abstractor_abstraction_id WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND COALESCE(sug.unknown, ?) = ? AND sug.suggested_value IS NOT NULL AND COALESCE(sug.suggested_value, '') != '' )", options[:namespace_type], options[:namespace_id], options[:abstractor_abstraction_schemas], false, false])
218
363
  else
219
364
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? AND sub.abstractor_abstraction_schema_id IN (?) WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id)", options[:namespace_type], options[:namespace_id], options[:abstractor_abstraction_schemas]])
@@ -222,7 +367,7 @@ module Abstractor
222
367
  case abstractor_suggestion_type
223
368
  when Abstractor::Enum::ABSTRACTION_SUGGESTION_TYPE_UNKNOWN
224
369
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.abstractor_abstraction_schema_id IN (?) JOIN abstractor_suggestions sug ON aa.id = sug.abstractor_abstraction_id WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND sug.unknown = ?)", options[:abstractor_abstraction_schemas], true])
225
- when Abstractor::Enum::ABSTRACTION_SUGGESTION_TYPE_NOT_UNKNOWN
370
+ when Abstractor::Enum::ABSTRACTION_SUGGESTION_TYPE_SUGGESTED
226
371
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.abstractor_abstraction_schema_id IN (?) JOIN abstractor_suggestions sug ON aa.id = sug.abstractor_abstraction_id WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND COALESCE(sug.unknown, ?) = ? AND sug.suggested_value IS NOT NULL AND COALESCE(sug.suggested_value, '') != '' )", options[:abstractor_abstraction_schemas], false, false])
227
372
  else
228
373
  where(nil)
@@ -235,7 +380,7 @@ module Abstractor
235
380
  #
236
381
  # * 'needs_review': Filter abstractable entites having at least one abstraction without a determined value (value, unknown or not_applicable).
237
382
  # * 'reviewed': Filter abstractable entites having no abstractions without a determined value (value, unknown or not_applicable).
238
- #
383
+ # * 'actually answered': Filter abstractable entites having no abstractions without an actual value (exluding blank, unknown or not_applicable).
239
384
  # @param [String] abstractor_abstraction_status Filter abstactable entities that an abstraction that 'needs_review' or are all abstractions are 'reviewed'.
240
385
  # @param [Hash] options the options to filter the entities returned.
241
386
  # @option options [String] :namespace_type The type parameter of the namespace to filter the entities.
@@ -250,6 +395,8 @@ module Abstractor
250
395
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND (aa.value IS NULL OR aa.value = '') AND (aa.unknown IS NULL OR aa.unknown = ?) AND (aa.not_applicable IS NULL OR aa.not_applicable = ?))", options[:namespace_type], options[:namespace_id], false, false])
251
396
  when Abstractor::Enum::ABSTRACTION_STATUS_REVIEWED
252
397
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id) AND NOT EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND COALESCE(aa.value, '') = '' AND COALESCE(aa.unknown, ?) != ? AND COALESCE(aa.not_applicable, ?) != ?)", options[:namespace_type], options[:namespace_id], options[:namespace_type], options[:namespace_id], false, true, false, true])
398
+ when Abstractor::Enum::ABSTRACTION_STATUS_ACTUALLY_ANSWERED
399
+ where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id) AND NOT EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND COALESCE(aa.value, '') = '')", options[:namespace_type], options[:namespace_id], options[:namespace_type], options[:namespace_id]])
253
400
  else
254
401
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa JOIN abstractor_subjects sub ON aa.abstractor_subject_id = sub.id AND sub.namespace_type = ? AND sub.namespace_id = ? WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id)", options[:namespace_type], options[:namespace_id]])
255
402
  end
@@ -259,6 +406,8 @@ module Abstractor
259
406
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND (aa.value IS NULL OR aa.value = '') AND (aa.unknown IS NULL OR aa.unknown = ?) AND (aa.not_applicable IS NULL OR aa.not_applicable = ?))", false, false])
260
407
  when Abstractor::Enum::ABSTRACTION_STATUS_REVIEWED
261
408
  where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id) AND NOT EXISTS (SELECT 1 FROM abstractor_abstractions aa WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND COALESCE(aa.value, '') = '' AND COALESCE(aa.unknown, ?) != ? AND COALESCE(aa.not_applicable, ?) != ?)", false, true, false, true])
409
+ when Abstractor::Enum::ABSTRACTION_STATUS_ACTUALLY_ANSWERED
410
+ where(["EXISTS (SELECT 1 FROM abstractor_abstractions aa WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id) AND NOT EXISTS (SELECT 1 FROM abstractor_abstractions aa WHERE aa.deleted_at IS NULL AND aa.about_type = '#{self.to_s}' AND #{self.table_name}.id = aa.about_id AND COALESCE(aa.value, '') = '')"])
262
411
  else
263
412
  where(nil)
264
413
  end
@@ -41,7 +41,11 @@ class String
41
41
  rng = range(pattern, i)
42
42
  if rng
43
43
  r << rng
44
- i += reuse ? 1 : rng.end + 1
44
+ if reuse
45
+ i +=1
46
+ else
47
+ i = rng.end + 1
48
+ end
45
49
  else
46
50
  break
47
51
  end
@@ -6,11 +6,12 @@ module Abstractor
6
6
 
7
7
  ABSTRACTION_STATUS_NEEDS_REVIEW = 'needs review'
8
8
  ABSTRACTION_STATUS_REVIEWED = 'reviewed'
9
- ABSTRACTION_STATUSES = [ABSTRACTION_STATUS_NEEDS_REVIEW, ABSTRACTION_STATUS_REVIEWED]
9
+ ABSTRACTION_STATUS_ACTUALLY_ANSWERED = 'actually answered'
10
+ ABSTRACTION_STATUSES = [ABSTRACTION_STATUS_NEEDS_REVIEW, ABSTRACTION_STATUS_REVIEWED, ABSTRACTION_STATUS_ACTUALLY_ANSWERED]
10
11
 
11
12
  ABSTRACTION_SUGGESTION_TYPE_UNKNOWN = 'unknown'
12
- ABSTRACTION_SUGGESTION_TYPE_NOT_UNKNOWN = 'not unknown'
13
- ABSTRACTION_SUGGESTION_TYPES = [ABSTRACTION_SUGGESTION_TYPE_UNKNOWN, ABSTRACTION_SUGGESTION_TYPE_NOT_UNKNOWN]
13
+ ABSTRACTION_SUGGESTION_TYPE_SUGGESTED = 'suggested'
14
+ ABSTRACTION_SUGGESTION_TYPES = [ABSTRACTION_SUGGESTION_TYPE_UNKNOWN, ABSTRACTION_SUGGESTION_TYPE_SUGGESTED]
14
15
 
15
16
  ABSTRACTOR_SECTION_TYPE_CUSTOM = 'custom'
16
17
  ABSTRACTOR_SECTION_TYPE_NAME_VALUE = 'name/value'
@@ -20,5 +21,6 @@ module Abstractor
20
21
  ABSTRACTOR_SUGGESTION_STATUS_ACCEPTED = 'Accepted'
21
22
  ABSTRACTOR_SUGGESTION_STATUS_REJECTED = 'Rejected'
22
23
  ABSTRACTOR_SUGGESTION_STATUSES = [ABSTRACTOR_SUGGESTION_STATUS_NEEDS_REVIEW, ABSTRACTOR_SUGGESTION_STATUS_ACCEPTED, ABSTRACTOR_SUGGESTION_STATUS_REJECTED]
24
+ ABSTRACTOR_GROUP_SENTINENTAL_SUBTYPE = 'sentinental'
23
25
  end
24
26
  end
@@ -15,7 +15,7 @@ module Abstractor
15
15
  abstractor_suggestion = nil
16
16
  Abstractor::AbstractorSuggestion.transaction do
17
17
  suggestion[:suggestion_sources].each do |suggestion_source|
18
- abstractor_suggestion = @abstractor_abstraction.abstractor_subject.suggest(@abstractor_abstraction, abstractor_abstraction_source, suggestion_source[:match_value], suggestion_source[:sentence_match_value], suggestion[:source_id], suggestion[:source_type], suggestion[:source_method], nil, suggestion[:value], suggestion[:unknown], suggestion[:not_applicable], nil, nil)
18
+ abstractor_suggestion = @abstractor_abstraction.abstractor_subject.suggest(@abstractor_abstraction, abstractor_abstraction_source, suggestion_source[:match_value], suggestion_source[:sentence_match_value], suggestion[:source_id], suggestion[:source_type], suggestion[:source_method], nil, suggestion[:value], suggestion[:unknown].to_s.to_boolean, suggestion[:not_applicable].to_s.to_boolean, nil, nil)
19
19
  end
20
20
  end
21
21
  format.json { render json: abstractor_suggestion, status: :created }
@@ -32,6 +32,10 @@ module Abstractor
32
32
  !system_generated
33
33
  end
34
34
 
35
+ def has_subtype?(s)
36
+ subtype == s
37
+ end
38
+
35
39
  private
36
40
  def update_abstractor_abstraction_group_members
37
41
  return unless deleted?
@@ -14,6 +14,13 @@ module Abstractor
14
14
  # base.send :attr_accessible, :deleted_at, :name
15
15
  # Validations
16
16
  base.send :validates, :cardinality, numericality: { only_integer: true, greater_than: 0 }, unless: Proc.new { |a| a.cardinality.blank? }
17
+ base.send(:include, InstanceMethods)
18
+ end
19
+
20
+ module InstanceMethods
21
+ def has_subtype?(s)
22
+ subtype == s
23
+ end
17
24
  end
18
25
  end
19
26
  end
@@ -7,7 +7,6 @@ module Abstractor
7
7
  options = { new_line_is_sentence_break: true }.merge(options)
8
8
  @abstractor_text = abstractor_text
9
9
 
10
- puts options[:new_line_is_sentence_break]
11
10
  if options[:new_line_is_sentence_break]
12
11
  StanfordCoreNLP.custom_properties['ssplit.newlineIsSentenceBreak'] = 'always'
13
12
  else
@@ -7,22 +7,24 @@ module Abstractor
7
7
  end
8
8
 
9
9
  def as_json(options = {})
10
- {
11
- "predicate" => abstractor_abstraction_schema.predicate,
12
- "display_name" => abstractor_abstraction_schema.display_name,
13
- "abstractor_object_type" => abstractor_abstraction_schema.abstractor_object_type.value,
14
- "preferred_name" => abstractor_abstraction_schema.preferred_name,
15
- "predicate_variants" => abstractor_abstraction_schema.abstractor_abstraction_schema_predicate_variants.map { |abstractor_abstraction_schema_predicate_variant| { 'value' => abstractor_abstraction_schema_predicate_variant.value } },
16
- "object_values" => abstractor_abstraction_schema.abstractor_object_values.map do |abstractor_object_value|
17
- {
18
- 'value' => abstractor_object_value.value,
19
- 'properties' => abstractor_object_value.properties.nil? ? nil : JSON.parse(abstractor_object_value.properties),
20
- 'vocabulary_code' => abstractor_object_value.vocabulary_code,
21
- 'vocabulary' => abstractor_object_value.vocabulary,
22
- 'vocabulary_version' => abstractor_object_value.vocabulary_version,
23
- 'object_value_variants' => abstractor_object_value.abstractor_object_value_variants.map { |abstractor_object_value_variant| { 'value' => abstractor_object_value_variant.value } }
24
- }
25
- end
10
+ { "abstractor_abstraction_schema" =>
11
+ {
12
+ "predicate" => abstractor_abstraction_schema.predicate,
13
+ "display_name" => abstractor_abstraction_schema.display_name,
14
+ "abstractor_object_type" => abstractor_abstraction_schema.abstractor_object_type.value,
15
+ "preferred_name" => abstractor_abstraction_schema.preferred_name,
16
+ "predicate_variants" => abstractor_abstraction_schema.abstractor_abstraction_schema_predicate_variants.map { |abstractor_abstraction_schema_predicate_variant| { 'value' => abstractor_abstraction_schema_predicate_variant.value } },
17
+ "object_values" => abstractor_abstraction_schema.abstractor_object_values.map do |abstractor_object_value|
18
+ {
19
+ 'value' => abstractor_object_value.value,
20
+ 'properties' => abstractor_object_value.properties.nil? ? nil : JSON.parse(abstractor_object_value.properties),
21
+ 'vocabulary_code' => abstractor_object_value.vocabulary_code,
22
+ 'vocabulary' => abstractor_object_value.vocabulary,
23
+ 'vocabulary_version' => abstractor_object_value.vocabulary_version,
24
+ 'object_value_variants' => abstractor_object_value.abstractor_object_value_variants.map { |abstractor_object_value_variant| { 'value' => abstractor_object_value_variant.value } }
25
+ }
26
+ end
27
+ }
26
28
  }
27
29
  end
28
30
 
@@ -1,3 +1,3 @@
1
1
  module Abstractor
2
- VERSION = '4.3.3'
2
+ VERSION = '4.4.0'
3
3
  end
@@ -58,18 +58,18 @@ module Abstractor
58
58
  unless options["no-install-stanford-core-nlp"]
59
59
  puts "Running rake abstractor:setup:stanford_core_nlp"
60
60
  puts 'Please be patient...this could take a while.'
61
- `rake abstractor:setup:stanford_core_nlp`
61
+ # `rake abstractor:setup:stanford_core_nlp`
62
62
 
63
63
  insert_into_file("#{Rails.root}/config/environments/development.rb", :after => /(::Application.configure do\n|application.configure do\n)/) do
64
64
  ' StanfordCoreNLP.use :english
65
65
  StanfordCoreNLP.model_files = {}
66
- StanfordCoreNLP.jar_path = "#{Rails.root}/lib/stanford-corenlp-full-2014-06-16/"
67
- StanfordCoreNLP.model_path = "#{Rails.root}/lib/stanford-corenlp-full-2014-06-16/"
66
+ StanfordCoreNLP.jar_path = "#{Rails.root}/lib/stanford-corenlp-full-2015-04-20/"
67
+ StanfordCoreNLP.model_path = "#{Rails.root}/lib/stanford-corenlp-full-2015-04-20/"
68
68
  StanfordCoreNLP.default_jars = [
69
69
  "joda-time.jar",
70
70
  "xom.jar",
71
- "stanford-corenlp-3.4.jar",
72
- "stanford-corenlp-3.4-models.jar",
71
+ "stanford-corenlp-3.5.2.jar",
72
+ "stanford-corenlp-3.5.2-models.jar",
73
73
  "jollyday.jar",
74
74
  "bridge.jar"
75
75
  ]
@@ -14,20 +14,20 @@ namespace :abstractor do
14
14
  Abstractor::Setup.system
15
15
  end
16
16
 
17
- desc "Setup Stanford CoreNLP library in lib/stanford-corenlp-full-2014-06-16/ directory"
17
+ desc "Setup Stanford CoreNLP library in lib/stanford-corenlp-full-2015-04-20/ directory"
18
18
  task :stanford_core_nlp => :environment do
19
19
  puts 'Please be patient...This could take a while.'
20
- file = "#{Rails.root}/lib/stanford-corenlp-full-2014-06-16.zip"
20
+ file = "#{Rails.root}/lib/stanford-corenlp-full-2015-04-20.zip"
21
21
  open(file, 'wb') do |fo|
22
- fo.print open('http://nlp.stanford.edu/software/stanford-corenlp-full-2014-06-16.zip').read
22
+ fo.print open('http://nlp.stanford.edu/software/stanford-corenlp-full-2015-04-20.zip').read
23
23
  end
24
24
 
25
- file = "#{Rails.root}/lib/stanford-corenlp-full-2014-06-16.zip"
25
+ file = "#{Rails.root}/lib/stanford-corenlp-full-2015-04-20.zip"
26
26
  destination = "#{Rails.root}/lib/"
27
27
  puts 'Unzipping...'
28
28
  unzip_file(file, destination)
29
29
 
30
- file = "#{Rails.root}/lib/stanford-corenlp-full-2014-06-16/bridge.jar"
30
+ file = "#{Rails.root}/lib/stanford-corenlp-full-2015-04-20/bridge.jar"
31
31
  open(file, 'wb') do |fo|
32
32
  fo.print open('https://github.com/louismullie/stanford-core-nlp/blob/master/bin/bridge.jar?raw=true').read
33
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abstractor
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.3
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Gurley, Yulia Bushmanova
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-25 00:00:00.000000000 Z
11
+ date: 2015-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -557,6 +557,9 @@ files:
557
557
  - db/migrate/20150223033848_add_custom_nlp_provider_to_abstractor_abstraction_sources.rb
558
558
  - db/migrate/20150317172523_add_properties_to_abstractor_object_values.rb
559
559
  - db/migrate/20150317204748_add_vocabulary_columns_to_abstractor_object_values.rb
560
+ - db/migrate/20150422135935_add_display_order_to_abstractor_abstraction_schema_object_values.rb
561
+ - db/migrate/20150423045055_add_subtype_to_abstractor_subject_groups.rb
562
+ - db/migrate/20150505022228_add_subtype_to_abstractor_abstraction_groups.rb
560
563
  - db/seeds.rb
561
564
  - lib/abstractor.rb
562
565
  - lib/abstractor/abstractable.rb