abstractor 4.4.1 → 4.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1915d3f9543f45ccc3df0b4e6c74d6b58f566398
4
- data.tar.gz: 5cb807386ae0cdfa2a60d28ef55b6d1bfddba633
3
+ metadata.gz: 07d9074db71c7f0389203998331177b329015321
4
+ data.tar.gz: 266b2bfeb642c6613ff23e12da66d904c90723f9
5
5
  SHA512:
6
- metadata.gz: 5503ed02f9a8b7d9b9c39fa2ab19b937b9f363adf1bece36b84b5365ef0ad138dd0cabf182dc59b1d881dcc84c1134cb65cd0ad5138741b00c4419089a7361ee
7
- data.tar.gz: ffa6167f82c4286ae712deb5f25b859eb74200d6e3ec266e26d8d0eab51d629db32348a0ccca3a72f814b0e0355c360e503d959a5f7dc8a4a196c3ddb2ed1d96
6
+ metadata.gz: fa9449c55a6b1600596d86fbaa55da291955a17e71a8f463cfa386687270e04654339d0e2e39441fbf7a418fb06d5e835124412c79092ae1ba6df6f092a2dd97
7
+ data.tar.gz: 1628fd3acdc7f26b12325cfb6666fed656937386faee9bb2b5de865f7d0744a2227e008f146fe2c454a7bfc450102f0ab74572f1a398e98023eb5a8be4507fa7
@@ -7,28 +7,28 @@
7
7
  = abstraction_schema.display_name
8
8
  .abstraction_edit_abstraction_value
9
9
  - case abstraction_schema.abstractor_object_type.value
10
- - when 'date'
10
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_DATE
11
11
  = f.text_field :value, class: 'abstractor_datepicker'
12
- - when 'text'
12
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_TEXT
13
13
  = f.text_area :value
14
- - when 'string'
14
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_STRING
15
15
  = f.text_field :value
16
- - when 'number'
16
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_NUMBER
17
17
  = f.number_field :value
18
- - when 'radio button list'
18
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_RADIO_BUTTON_LIST
19
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
- - when 'list'
25
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_LIST, Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_NUMBER_LIST
26
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
- - when 'dynamic list'
28
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_DYNAMIC_LIST
29
29
  - values = abstractor_abstraction.about.send(abstractor_abstraction.abstractor_subject.dynamic_list_method).sort_by { |l| l[:value] }
30
30
  = f.select :value, values.map{|s| [s[:value], s[:id]]}, {:include_blank => true}, :class => "combobox"
31
- - when 'boolean'
31
+ - when Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_BOOLEAN
32
32
  - ['true', 'false'].each do |value|
33
33
  = f.radio_button :value, value
34
34
  = f.label :value, value
@@ -21,6 +21,30 @@ module Abstractor
21
21
  ABSTRACTOR_SUGGESTION_STATUS_ACCEPTED = 'Accepted'
22
22
  ABSTRACTOR_SUGGESTION_STATUS_REJECTED = 'Rejected'
23
23
  ABSTRACTOR_SUGGESTION_STATUSES = [ABSTRACTOR_SUGGESTION_STATUS_NEEDS_REVIEW, ABSTRACTOR_SUGGESTION_STATUS_ACCEPTED, ABSTRACTOR_SUGGESTION_STATUS_REJECTED]
24
+
24
25
  ABSTRACTOR_GROUP_SENTINENTAL_SUBTYPE = 'sentinental'
26
+
27
+ ABSTRACTOR_OBJECT_TYPE_LIST = 'list'
28
+ ABSTRACTOR_OBJECT_TYPE_NUMBER = 'number'
29
+ ABSTRACTOR_OBJECT_TYPE_BOOLEAN = 'boolean'
30
+ ABSTRACTOR_OBJECT_TYPE_STRING = 'string'
31
+ ABSTRACTOR_OBJECT_TYPE_RADIO_BUTTON_LIST = 'radio button list'
32
+ ABSTRACTOR_OBJECT_TYPE_DATE = 'date'
33
+ ABSTRACTOR_OBJECT_TYPE_DYNAMIC_LIST = 'dynamic list'
34
+ ABSTRACTOR_OBJECT_TYPE_TEXT = 'text'
35
+ ABSTRACTOR_OBJECT_TYPE_NUMBER_LIST = 'number list'
36
+ ABSTRACTOR_OBJECT_TYPES = [
37
+ ABSTRACTOR_OBJECT_TYPE_LIST,
38
+ ABSTRACTOR_OBJECT_TYPE_NUMBER,
39
+ ABSTRACTOR_OBJECT_TYPE_BOOLEAN,
40
+ ABSTRACTOR_OBJECT_TYPE_STRING,
41
+ ABSTRACTOR_OBJECT_TYPE_RADIO_BUTTON_LIST,
42
+ ABSTRACTOR_OBJECT_TYPE_DATE,
43
+ ABSTRACTOR_OBJECT_TYPE_DYNAMIC_LIST,
44
+ ABSTRACTOR_OBJECT_TYPE_TEXT,
45
+ ABSTRACTOR_OBJECT_TYPE_NUMBER_LIST
46
+ ]
47
+
48
+ NUMERIC_REGEX = '(?<object_value>\d+[\.,]*\d*[\.,]*\d*)'
25
49
  end
26
50
  end
@@ -8,7 +8,17 @@ module Abstractor
8
8
  # Associations
9
9
  base.send :has_many, :abstractor_abstraction_schemas
10
10
 
11
- # base.send :attr_accessible, :deleted_at, :value
11
+ base.send(:include, InstanceMethods)
12
+ end
13
+
14
+ module InstanceMethods
15
+ def number?
16
+ self.value == Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_NUMBER
17
+ end
18
+
19
+ def number_list?
20
+ self.value == Abstractor::Enum::ABSTRACTOR_OBJECT_TYPE_NUMBER_LIST
21
+ end
12
22
  end
13
23
  end
14
24
  end
@@ -238,65 +238,120 @@ module Abstractor
238
238
  end
239
239
  end
240
240
 
241
+ # Generates suggestions for name/value pairs.
242
+ #
243
+ # Tht method will detect sentenses in the source text that match any of the predicate variants.
244
+ # For each detected sentence, method would first try to abstract canonical name/value pair.
245
+ # If canonical match was not found, method would try to abstract sentinental match.
246
+ #
247
+ # @param [ActiveRecord::Base] about The entity to abstract. An instance of the class specified in the Abstractor::AbstractorSubject#subject_type attribute.
248
+ # @param [Abstractor::AbstractorAbstraction] abstractor_abstraction The instance of Abstractor::AbstractorAbstraction to make suggestions against.
249
+ # @param [Abstractor::AbstractorAbstractionSource] abstractor_abstraction_source The instance of the Abstractor::AbstractorAbstractionSource that provides the custom method to invoke on the abstractable entity to make custom suggestions.
250
+ # @return [void]
241
251
  def abstract_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
242
- abstract_canonical_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
243
- abstract_sentential_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
244
- create_unknown_abstractor_suggestion_name_only(about, abstractor_abstraction, abstractor_abstraction_source)
245
- create_unknown_abstractor_suggestion(about, abstractor_abstraction, abstractor_abstraction_source)
246
- end
247
-
248
- def abstract_canonical_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
249
252
  abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
250
253
  abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
251
254
  parser = Abstractor::Parser.new(abstractor_text)
255
+
252
256
  abstractor_abstraction_schema.predicate_variants.each do |predicate_variant|
253
- abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
254
- abstractor_object_value.object_variants.each do |object_variant|
255
- match_value = "#{Regexp.escape(predicate_variant)}:\s*#{Regexp.escape(object_variant)}"
256
- matches = parser.scan(match_value, word_boundary: true).uniq
257
- matches.each do |match|
258
- suggest(abstractor_abstraction, abstractor_abstraction_source, match, match, source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
259
- end
257
+ ranges = parser.range_all(Regexp.escape(predicate_variant), word_boundary: false)
258
+ ranges.each do |range|
259
+ sentence = parser.find_sentence(range)
260
+ if sentence
261
+ is_abstracted = abstract_canonical_name_value(about, abstractor_abstraction, abstractor_abstraction_source, source, parser, sentence, predicate_variant)
262
+ abstract_sentential_name_value(about, abstractor_abstraction, abstractor_abstraction_source, source, parser, sentence, predicate_variant) unless is_abstracted
263
+ end
264
+ end
265
+ end
266
+ end
267
+ create_unknown_abstractor_suggestion_name_only(about, abstractor_abstraction, abstractor_abstraction_source)
268
+ create_unknown_abstractor_suggestion(about, abstractor_abstraction, abstractor_abstraction_source)
269
+ end
260
270
 
261
- match_value = "#{Regexp.escape(predicate_variant)}#{Regexp.escape(object_variant)}"
262
- matches = parser.scan(match_value, word_boundary: true).uniq
271
+ def abstract_canonical_name_value(about, abstractor_abstraction, abstractor_abstraction_source, source, parser, sentence, predicate_variant)
272
+ is_abstracted = false
273
+ if abstractor_abstraction_schema.abstractor_object_type && (abstractor_abstraction_schema.abstractor_object_type.number? || abstractor_abstraction_schema.abstractor_object_type.number_list?)
274
+ object_regex = Abstractor::Enum::NUMERIC_REGEX
275
+
276
+ match_values = ["#{Regexp.escape(predicate_variant)}:\s*#{object_regex}", "#{Regexp.escape(predicate_variant)}#{object_regex}"]
277
+ match_values.each do |match_value|
278
+ matches = parser.sentence_match_scan(sentence[:sentence], match_value, word_boundary: true).uniq
279
+ if abstractor_abstraction_schema.abstractor_object_type.number_list?
280
+ # filter matched numbers by list of available values
281
+ abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
282
+ abstractor_object_value.object_variants.each do |object_variant|
283
+ matches.each do |match|
284
+ if object_variant == match[:object_value]
285
+ suggest(abstractor_abstraction, abstractor_abstraction_source, match.to_s, match.to_s, source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
286
+ end
287
+ end
288
+ end
289
+ end
290
+ else
291
+ matches.each do |match|
292
+ is_abstracted = suggest(abstractor_abstraction, abstractor_abstraction_source, match.to_s, match.to_s, source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], match[:object_value], nil, nil, nil, nil)
293
+ end
294
+ end
295
+ end
296
+ else
297
+ abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
298
+ abstractor_object_value.object_variants.each do |object_variant|
299
+ match_values = ["#{Regexp.escape(predicate_variant)}:\s*#{Regexp.escape(object_variant)}", "#{Regexp.escape(predicate_variant)}#{Regexp.escape(object_variant)}"]
300
+ match_values.each do |match_value|
301
+ matches = parser.sentence_scan(sentence[:sentence], match_value, word_boundary: true).uniq
263
302
  matches.each do |match|
264
- suggest(abstractor_abstraction, abstractor_abstraction_source, match, match, source[:source_id], source[:source_type].to_s, source[:source_method], source[:seciton_name], abstractor_object_value, nil, nil, nil, nil)
303
+ is_abstracted = suggest(abstractor_abstraction, abstractor_abstraction_source, match, match, source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
265
304
  end
266
305
  end
267
306
  end
268
307
  end
269
308
  end
309
+ is_abstracted
270
310
  end
271
311
 
272
- def abstract_sentential_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
273
- abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
274
- abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
275
- parser = Abstractor::Parser.new(abstractor_text)
276
- abstractor_abstraction_schema.predicate_variants.each do |predicate_variant|
277
- ranges = parser.range_all(Regexp.escape(predicate_variant))
278
- if ranges.any?
279
- ranges.each do |range|
280
- sentence = parser.find_sentence(range)
281
- if sentence
282
- abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
283
- abstractor_object_value.object_variants.each do |object_variant|
284
- match = parser.match_sentence(sentence[:sentence], Regexp.escape(object_variant))
285
- if match
286
- scoped_sentence = Abstractor::NegationDetection.parse_negation_scope(sentence[:sentence])
287
- reject = (
288
- Abstractor::NegationDetection.negated_match_value?(scoped_sentence[:scoped_sentence], predicate_variant) ||
289
- Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], predicate_variant) ||
290
- Abstractor::NegationDetection.negated_match_value?(scoped_sentence[:scoped_sentence], object_variant) ||
291
- Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], object_variant)
292
- )
293
- if !reject
294
- suggest(abstractor_abstraction, abstractor_abstraction_source, sentence[:sentence], sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
295
- end
296
- end
312
+ def abstract_sentential_name_value(about, abstractor_abstraction, abstractor_abstraction_source, source, parser, sentence, predicate_variant)
313
+ is_abstracted = false
314
+ if abstractor_abstraction_schema.abstractor_object_type && (abstractor_abstraction_schema.abstractor_object_type.number? || abstractor_abstraction_schema.abstractor_object_type.number_list?)
315
+ object_regex = object_regex = Abstractor::Enum::NUMERIC_REGEX
316
+ match = parser.match_sentence(sentence[:sentence], object_regex)
317
+ if match
318
+ scoped_sentence = Abstractor::NegationDetection.parse_negation_scope(sentence[:sentence])
319
+ reject = (
320
+ Abstractor::NegationDetection.negated_match_value?(scoped_sentence[:scoped_sentence], predicate_variant) ||
321
+ Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], predicate_variant) ||
322
+ Abstractor::NegationDetection.negated_match_value?(scoped_sentence[:scoped_sentence], match[:object_value]) ||
323
+ Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], match[:object_value])
324
+ )
325
+ if !reject
326
+ if abstractor_abstraction_schema.abstractor_object_type.number_list?
327
+ # filter matched numbers by list of available values
328
+ abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
329
+ abstractor_object_value.object_variants.each do |object_variant|
330
+ if object_variant == match[:object_value]
331
+ suggest(abstractor_abstraction, abstractor_abstraction_source, sentence[:sentence], sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
297
332
  end
298
333
  end
299
334
  end
335
+ else
336
+ is_abstracted = suggest(abstractor_abstraction, abstractor_abstraction_source, sentence[:sentence], sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], match[:object_value], nil, nil, nil, nil)
337
+ end
338
+ end
339
+ end
340
+ else
341
+ abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
342
+ abstractor_object_value.object_variants.each do |object_variant|
343
+ match = parser.match_sentence(sentence[:sentence], Regexp.escape(object_variant))
344
+ if match
345
+ scoped_sentence = Abstractor::NegationDetection.parse_negation_scope(sentence[:sentence])
346
+ reject = (
347
+ Abstractor::NegationDetection.negated_match_value?(scoped_sentence[:scoped_sentence], predicate_variant) ||
348
+ Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], predicate_variant) ||
349
+ Abstractor::NegationDetection.negated_match_value?(scoped_sentence[:scoped_sentence], object_variant) ||
350
+ Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], object_variant)
351
+ )
352
+ if !reject
353
+ is_abstracted = suggest(abstractor_abstraction, abstractor_abstraction_source, sentence[:sentence], sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
354
+ end
300
355
  end
301
356
  end
302
357
  end
@@ -377,7 +432,7 @@ module Abstractor
377
432
  def create_unknown_abstractor_suggestion(about, abstractor_abstraction, abstractor_abstraction_source)
378
433
  #Create an 'unknown' suggestion based on matching nothing only if we have not made a suggstion
379
434
  abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
380
- if abstractor_abstraction.abstractor_suggestions(true).select { |abstractor_suggestion| abstractor_suggestion.unknown != true }.empty?
435
+ if abstractor_abstraction.abstractor_suggestions(true).select { |abstractor_suggestion| abstractor_suggestion.unknown != true || abstractor_suggestion.unknown == true}.empty?
381
436
  suggest(abstractor_abstraction, abstractor_abstraction_source, nil, nil, source[:source_id], source[:source_type].to_s, source[:source_method],source[:section_name], nil, true, nil, nil, nil)
382
437
  end
383
438
  end
@@ -28,8 +28,8 @@ module Abstractor
28
28
  end
29
29
  end
30
30
 
31
- def scan(token, options = {})
32
- options[:word_boundary] = true if options[:word_boundary].nil?
31
+ def scan(token, options = {})
32
+ options[:word_boundary] = true if options[:word_boundary].nil?
33
33
  regular_expression = prepare_token(token, options)
34
34
  at = prepare_abstractor_text
35
35
  if (regular_expression.nil? || at.nil?)
@@ -39,13 +39,35 @@ module Abstractor
39
39
  end
40
40
  end
41
41
 
42
+ def sentence_scan(sentence, token, options = {})
43
+ options[:word_boundary] = true if options[:word_boundary].nil?
44
+ regular_expression = prepare_token(token, options)
45
+ if (regular_expression.nil? || sentence.nil?)
46
+ []
47
+ else
48
+ sentence.scan(regular_expression)
49
+ end
50
+ end
51
+
52
+ def sentence_match_scan(sentence, token, options = {})
53
+ options[:word_boundary] = true if options[:word_boundary].nil?
54
+ regular_expression = prepare_token(token, options)
55
+ if (regular_expression.nil? || sentence.nil?)
56
+ []
57
+ else
58
+ # http://stackoverflow.com/questions/6804557/how-do-i-get-the-match-data-for-all-occurrences-of-a-ruby-regular-expression-in
59
+ sentence.to_enum(:scan,regular_expression).map{ Regexp.last_match }
60
+ end
61
+ end
62
+
42
63
  def match(token)
43
64
  regular_expression = prepare_token(token)
44
65
  prepare_abstractor_text.match(regular_expression) unless regular_expression.nil?
45
66
  end
46
67
 
47
- def range_all(token)
48
- regular_expression = prepare_token(token)
68
+ def range_all(token, options = {})
69
+ options[:word_boundary] = true if options[:word_boundary].nil?
70
+ regular_expression = prepare_token(token, options)
49
71
  prepare_abstractor_text.range_all(regular_expression) unless regular_expression.nil?
50
72
  end
51
73
 
@@ -2,14 +2,9 @@ module Abstractor
2
2
  module Setup
3
3
  def self.system
4
4
  puts 'Setting up Abstractor::AbstractorObjectType'
5
- Abstractor::AbstractorObjectType.where(value: 'list').first_or_create
6
- Abstractor::AbstractorObjectType.where(value: 'number').first_or_create
7
- Abstractor::AbstractorObjectType.where(value: 'boolean').first_or_create
8
- Abstractor::AbstractorObjectType.where(value: 'string').first_or_create
9
- Abstractor::AbstractorObjectType.where(value: 'radio button list').first_or_create
10
- Abstractor::AbstractorObjectType.where(value: 'date').first_or_create
11
- Abstractor::AbstractorObjectType.where(value: 'dynamic list').first_or_create
12
- Abstractor::AbstractorObjectType.where(value: 'text').first_or_create
5
+ Abstractor::Enum::ABSTRACTOR_OBJECT_TYPES.each do |abstractor_object_type|
6
+ Abstractor::AbstractorObjectType.where(value: abstractor_object_type).first_or_create
7
+ end
13
8
 
14
9
  puts 'Setting up Abstractor::AbstractorRuleType'
15
10
  Abstractor::AbstractorRuleType.where(name: 'name/value', description:'search for value associated with name').first_or_create
@@ -1,3 +1,3 @@
1
1
  module Abstractor
2
- VERSION = '4.4.1'
2
+ VERSION = '4.4.2'
3
3
  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.4.1
4
+ version: 4.4.2
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-05-11 00:00:00.000000000 Z
11
+ date: 2015-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -845,7 +845,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
845
845
  version: '0'
846
846
  requirements: []
847
847
  rubyforge_project:
848
- rubygems_version: 2.4.3
848
+ rubygems_version: 2.2.2
849
849
  signing_key:
850
850
  specification_version: 4
851
851
  summary: A Rails engine gem for deriving discrete data points from narrative text