abstractor 4.0.2 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/app/assets/javascripts/abstractor/abstractor.js.coffee +13 -4
- data/app/models/abstractor/abstractor_section.rb +5 -0
- data/app/models/abstractor/abstractor_section_name_variant.rb +5 -0
- data/app/models/abstractor/abstractor_section_type.rb +5 -0
- data/app/views/abstractor/abstractor_abstraction_groups/_form.html.haml +7 -2
- data/app/views/abstractor/abstractor_abstraction_groups/edit.html.haml +4 -1
- data/app/views/abstractor/abstractor_abstractions/_fields.html.haml +9 -9
- data/app/views/abstractor/abstractor_abstractions/_grouped_abstractions_list.html.haml +8 -2
- data/app/views/abstractor/abstractor_abstractions/edit.html.haml +3 -2
- data/db/migrate/20141028020332_add_cardinality_to_abstractor_subject_group.rb +5 -0
- data/db/migrate/20141107171413_add_sectioning.rb +41 -0
- data/lib/abstractor/abstractable.rb +24 -5
- data/lib/abstractor/enum.rb +3 -0
- data/lib/abstractor/methods/controllers/abstractor_abstraction_groups_controller.rb +13 -4
- data/lib/abstractor/methods/models/abstractor_abstraction.rb +2 -0
- data/lib/abstractor/methods/models/abstractor_abstraction_group.rb +32 -14
- data/lib/abstractor/methods/models/abstractor_abstraction_group_member.rb +2 -0
- data/lib/abstractor/methods/models/abstractor_abstraction_source.rb +32 -2
- data/lib/abstractor/methods/models/abstractor_section.rb +23 -0
- data/lib/abstractor/methods/models/abstractor_section_name_variant.rb +14 -0
- data/lib/abstractor/methods/models/abstractor_section_type.rb +14 -0
- data/lib/abstractor/methods/models/abstractor_subject.rb +14 -13
- data/lib/abstractor/methods/models/abstractor_subject_group.rb +2 -0
- data/lib/abstractor/methods/models/abstractor_suggestion.rb +3 -2
- data/lib/abstractor/setup.rb +4 -0
- data/lib/abstractor/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzNiYjAyNWRiMDJhYzQwODJkMjJkNDFjMDIzMGRiYzM4NDA1MzZlMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTVlMmQxZjFhM2M3Y2I2NGI5ODQ4ODE5MGVlY2M0MDAxNWZjNWYwOA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDhkMGRhZjc3ZmNkODk3ZmFhMjYwNTY2OTQxZGVjYWUyMjAyZDczOTA4ZmY0
|
10
|
+
YzAwNDc1YWVjYmNiOGFjNDM5ODU0NmQ0YzBlMDY1YjNlMjg3ZTFmOTM3NTA1
|
11
|
+
YzE2NjEyMGYyYjdjYWJmODRmMjAyZjIxZmVjOTdhNzQ2ZjlkOTI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MDRkN2U5MDg1YTUxNzQzM2EwYmFmNzcxYjc1MTAzMjZkNmViNDdjZDdiNGQ0
|
14
|
+
YmVkYjhkZDE0NjlmNzNmMWJjODhmMzA0NTU5NTFmODA5MzVlMzY2NzhkYTM2
|
15
|
+
OTdkNmU4NjZkNDU3MWRlYTlmOTc4YzdkOWIxNzk1N2QyY2ZjNDc=
|
@@ -84,18 +84,28 @@ Abstractor.AbstractionSuggestionUI = ->
|
|
84
84
|
$(document).on "ajax:success", "form.edit_abstractor_suggestion", (e, data, status, xhr) ->
|
85
85
|
$(this).closest(".abstractor_abstraction").html xhr.responseText
|
86
86
|
return
|
87
|
-
|
88
87
|
return
|
89
88
|
|
90
89
|
Abstractor.AbstractionGroupUI = ->
|
90
|
+
validateCardinality = (group_container) ->
|
91
|
+
group_cardinality = group_container.find('input[name="abstractor_subject_group_cardinality"]')
|
92
|
+
add_group_link = group_container.find('.abstractor_group_add_link')
|
93
|
+
if (group_cardinality.length > 0) && (group_cardinality.val() == group_container.find('.abstractor_abstraction_group_member').length.toString())
|
94
|
+
$(add_group_link).hide()
|
95
|
+
else
|
96
|
+
$(add_group_link).show()
|
97
|
+
|
91
98
|
$(document).on "ajax:success", ".abstractor_abstraction_group .abstractor_group_delete_link", (e, data, status, xhr) ->
|
92
|
-
|
93
|
-
|
99
|
+
subject_groups_container_div = $(this).closest(".abstractor_subject_groups_container")
|
100
|
+
abstraction_group_div = $(this).closest(".abstractor_abstraction_group")
|
101
|
+
abstraction_group_div.html xhr.responseText
|
102
|
+
validateCardinality(subject_groups_container_div)
|
94
103
|
return
|
95
104
|
|
96
105
|
$(document).on "ajax:success", ".abstractor_subject_groups_container .abstractor_group_add_link", (e, data, status, xhr) ->
|
97
106
|
parent_div = $(this).closest(".abstractor_subject_groups_container")
|
98
107
|
parent_div.find(".abstractor_subject_groups").append xhr.responseText
|
108
|
+
validateCardinality(parent_div)
|
99
109
|
return
|
100
110
|
|
101
111
|
$(document).on "ajax:success", ".abstractor_abstraction_group .abstractor_group_not_applicable_all_link", (e, data, status, xhr) ->
|
@@ -107,7 +117,6 @@ Abstractor.AbstractionGroupUI = ->
|
|
107
117
|
parent_div = $(this).closest(".abstractor_abstraction_group")
|
108
118
|
parent_div.html xhr.responseText
|
109
119
|
return
|
110
|
-
|
111
120
|
return
|
112
121
|
|
113
122
|
new Abstractor.AbstractionUI()
|
@@ -1,9 +1,14 @@
|
|
1
|
+
- namespace_type ||= @namespace_type
|
2
|
+
- namespace_id ||= @namespace_id
|
3
|
+
|
1
4
|
- abstractor_abstraction_group ||= @abstractor_abstraction_group
|
2
5
|
|
3
6
|
.abstractor_abstraction_group
|
4
7
|
.abstractor_abstraction_group_member
|
5
|
-
- abstractor_abstractions = abstractor_abstraction_group.abstractor_abstractions.not_deleted.joins(:abstractor_subject => :abstractor_subject_group_member)
|
6
|
-
-
|
8
|
+
- abstractor_abstractions = abstractor_abstraction_group.abstractor_abstractions.not_deleted.joins(:abstractor_subject => :abstractor_subject_group_member)
|
9
|
+
- unless namespace_type.blank? || namespace_id.blank?
|
10
|
+
- abstractor_abstractions = abstractor_abstractions.where(abstractor_subjects: { namespace_type: namespace_type, namespace_id: namespace_id})
|
11
|
+
- abstractor_abstractions.order('abstractor_subject_group_members.display_order').each_with_index do |abstractor_abstraction, index|
|
7
12
|
%div{ class: "abstractor_abstraction #{Abstractor::Utility.dehumanize(abstractor_abstraction.abstractor_subject.abstractor_abstraction_schema.predicate)} #{'abstractor_bottom_border' if index < abstractor_abstractions.length - 1}" }
|
8
13
|
= render :partial => 'abstractor/abstractor_abstractions/fields', :locals => {:abstractor_abstraction => abstractor_abstraction}
|
9
14
|
.abstractor_abstraction_group_actions.abstractor_abstraction_actions
|
@@ -27,18 +27,17 @@
|
|
27
27
|
= abstractor_suggestion.display_value
|
28
28
|
- if abstractor_suggestion.abstractor_suggestion_sources.any?
|
29
29
|
- abstractor_suggestion.abstractor_suggestion_sources.each do |abstractor_suggestion_source|
|
30
|
-
-
|
31
|
-
-
|
32
|
-
- if
|
33
|
-
-
|
34
|
-
|
35
|
-
%span{ class: 'abstractor_abstraction_source_tooltip_img', rel: "#abstraction_text_#{abstractor_suggestion_source.id}", title: "#{source_about.class.to_s} #{from_method}"}
|
30
|
+
- source = { source_type: abstractor_suggestion_source.source_type.constantize, source_id: abstractor_suggestion_source.source_id , source_method: abstractor_suggestion_source.source_method, section_name: abstractor_suggestion_source.section_name }
|
31
|
+
- abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
32
|
+
- if abstractor_text
|
33
|
+
- has_text_match = abstractor_text && abstractor_suggestion_source.sentence_match_value
|
34
|
+
%span{ class: 'abstractor_abstraction_source_tooltip_img', rel: "#abstraction_text_#{abstractor_suggestion_source.id}", title: "#{abstractor_suggestion_source.source_type} #{abstractor_suggestion_source.source_method}"}
|
36
35
|
%i{ id: "abstraction_text_link_#{abstractor_suggestion_source.id}", class: "#{'abstraction_text_link_match' if has_text_match}" }
|
37
36
|
%div{ id: "abstraction_text_#{abstractor_suggestion_source.id}", class: 'abstractor_abstraction_source_tooltip'}
|
38
37
|
- if has_text_match
|
39
|
-
= Abstractor::UserInterface.highlight(simple_format(
|
38
|
+
= Abstractor::UserInterface.highlight(simple_format(abstractor_text), abstractor_suggestion_source.sentence_match_value.strip)
|
40
39
|
- else
|
41
|
-
= simple_format(
|
40
|
+
= simple_format(abstractor_text)
|
42
41
|
- if abstractor_suggestion_source.custom_explanation
|
43
42
|
.custom_explanation
|
44
43
|
%label
|
@@ -62,5 +61,6 @@
|
|
62
61
|
%i{ id: "abstraction_text_link_#{dom_id}" }
|
63
62
|
%br
|
64
63
|
%div{ id: "abstraction_text_#{dom_id}", class: 'tooltip'}
|
65
|
-
=
|
64
|
+
- abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
65
|
+
= simple_format(abstractor_text)
|
66
66
|
.clear
|
@@ -1,8 +1,13 @@
|
|
1
|
+
- namespace_type ||= @namespace_type
|
2
|
+
- namespace_id ||= @namespace_id
|
3
|
+
|
1
4
|
.abstractor_abstractions_grouped
|
2
5
|
- abstractor_subject_groups = about.class.abstractor_subject_groups(namespace_type: namespace_type, namespace_id: namespace_id)
|
3
6
|
- abstractor_subject_groups.each do |abstractor_subject_group|
|
4
7
|
.abstractor_subject_groups_container
|
5
8
|
%b= abstractor_subject_group.name
|
9
|
+
- if abstractor_subject_group.cardinality
|
10
|
+
= hidden_field_tag :abstractor_subject_group_cardinality, abstractor_subject_group.cardinality, id: "abstractor_subject_group_cardinality_#{abstractor_subject_group.id}"
|
6
11
|
%fieldset
|
7
12
|
.abstractor_abstractions_header
|
8
13
|
.abstractor_abstraction_schema_name
|
@@ -18,6 +23,7 @@
|
|
18
23
|
.abstractor_abstractions_body.abstractor_subject_groups
|
19
24
|
- abstractor_abstraction_groups = about.abstractor_abstraction_groups_by_namespace(namespace_type: namespace_type, namespace_id: namespace_id, abstractor_subject_group_id: abstractor_subject_group.id)
|
20
25
|
- abstractor_abstraction_groups.each do |abstractor_abstraction_group|
|
21
|
-
= render partial: 'abstractor/abstractor_abstraction_groups/form', locals: {abstractor_abstraction_group: abstractor_abstraction_group}
|
22
|
-
|
26
|
+
= render partial: 'abstractor/abstractor_abstraction_groups/form', locals: {abstractor_abstraction_group: abstractor_abstraction_group, namespace_type: namespace_type, namespace_id: namespace_id}
|
27
|
+
- unless abstractor_subject_group.cardinality == 1
|
28
|
+
= link_to 'Add group', Abstractor::UserInterface.abstractor_relative_path(abstractor.abstractor_abstraction_groups_path(about_id: about.id, about_type: about.class.name, abstractor_subject_group_id: abstractor_subject_group.id, namespace_type: namespace_type, namespace_id: namespace_id)), data: { confirm: 'Are you sure?'}, method: :post, class: 'abstractor_group_add_link', remote: true, style: "#{'display: none;' if about.abstractor_subject_group_complete?(abstractor_subject_group.id, {namespace_type: namespace_type, namespace_id: namespace_id})}"
|
23
29
|
.clear
|
@@ -45,13 +45,14 @@
|
|
45
45
|
- abstraction_sources = abstractor_abstraction.abstractor_subject.abstractor_abstraction_sources.select { |s| s.abstractor_abstraction_source_type.name != 'indirect' }
|
46
46
|
- abstraction_sources.each do |abstraction_source|
|
47
47
|
- abstraction_source.normalize_from_method_to_sources(abstractor_abstraction.about).each do |source|
|
48
|
-
-
|
48
|
+
- abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
49
|
+
- if abstractor_text
|
49
50
|
- dom_id = "#{abstraction_source.id}_#{source[:source_type]}_#{source[:source_id]}_#{source[:source_method]}"
|
50
51
|
%span{ :class => 'abstractor_abstraction_source_tooltip_img', :rel =>"#abstraction_text_#{dom_id}", :title => "#{source[:source_type].to_s} #{source[:source_method]}"}
|
51
52
|
= image_tag('abstractor/page.png', :id => "abstraction_text_link_#{dom_id}")
|
52
53
|
%br
|
53
54
|
%div{ :id => "abstraction_text_#{dom_id}", :class => 'tooltip'}
|
54
|
-
= simple_format(
|
55
|
+
= simple_format(abstractor_text)
|
55
56
|
.abstraction_edit_abstraction_actions
|
56
57
|
= f.submit 'Save'
|
57
58
|
= link_to 'Cancel', abstractor_abstraction, :remote => true
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class AddSectioning < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
create_table :abstractor_sections do |t|
|
4
|
+
t.integer :abstractor_section_type_id
|
5
|
+
t.string :source_type
|
6
|
+
t.string :source_method
|
7
|
+
t.string :name
|
8
|
+
t.string :description
|
9
|
+
t.string :delimiter
|
10
|
+
t.string :custom_regular_expression
|
11
|
+
t.boolean :return_note_on_empty_section
|
12
|
+
t.datetime :deleted_at
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :abstractor_section_types do |t|
|
17
|
+
t.string :name
|
18
|
+
t.string :regular_expression
|
19
|
+
t.datetime :deleted_at
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
|
23
|
+
create_table :abstractor_section_name_variants do |t|
|
24
|
+
t.integer :abstractor_section_id
|
25
|
+
t.string :name
|
26
|
+
t.datetime :deleted_at
|
27
|
+
t.timestamps
|
28
|
+
end
|
29
|
+
|
30
|
+
add_column :abstractor_abstraction_sources, :section_name, :string
|
31
|
+
add_column :abstractor_suggestion_sources, :section_name, :string
|
32
|
+
end
|
33
|
+
|
34
|
+
def down
|
35
|
+
drop_table :abstractor_sections
|
36
|
+
drop_table :abstractor_section_types
|
37
|
+
drop_table :abstractor_section_name_variants
|
38
|
+
remove_column :abstractor_abstraction_sources, :section_name
|
39
|
+
remove_column :abstractor_suggestion_sources, :section_name
|
40
|
+
end
|
41
|
+
end
|
@@ -76,7 +76,7 @@ module Abstractor
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def detect_abstractor_abstraction(abstractor_subject)
|
79
|
-
abstractor_abstractions(true).not_deleted.detect { |abstractor_abstraction| abstractor_abstraction.
|
79
|
+
abstractor_abstractions(true).not_deleted.detect { |abstractor_abstraction| abstractor_abstraction.abstractor_subject_id == abstractor_subject.id }
|
80
80
|
end
|
81
81
|
|
82
82
|
def find_or_create_abstractor_abstraction(abstractor_abstraction_schema, abstractor_subject)
|
@@ -84,25 +84,44 @@ module Abstractor
|
|
84
84
|
else
|
85
85
|
abstractor_abstraction = Abstractor::AbstractorAbstraction.create!(abstractor_subject: abstractor_subject, about: self)
|
86
86
|
if abstractor_subject.groupable?
|
87
|
-
abstractor_abstraction_group =
|
87
|
+
abstractor_abstraction_group = find_or_initialize_abstractor_abstraction_group(abstractor_subject.abstractor_subject_group)
|
88
88
|
abstractor_abstraction_group.abstractor_abstractions << abstractor_abstraction
|
89
|
+
abstractor_abstraction_group.save!
|
89
90
|
end
|
90
91
|
end
|
91
92
|
abstractor_abstraction
|
92
93
|
end
|
93
94
|
|
94
95
|
def detect_abstractor_abstraction_group(abstractor_subject_group)
|
95
|
-
abstractor_abstraction_groups(true).detect { |abstractor_abstraction_group| abstractor_abstraction_group.
|
96
|
+
abstractor_abstraction_groups(true).detect { |abstractor_abstraction_group| abstractor_abstraction_group.abstractor_subject_group_id == abstractor_subject_group.id }
|
96
97
|
end
|
97
98
|
|
98
|
-
def
|
99
|
+
def find_or_initialize_abstractor_abstraction_group(abstractor_subject_group)
|
99
100
|
if abstractor_abstraction_group = detect_abstractor_abstraction_group(abstractor_subject_group)
|
100
101
|
else
|
101
|
-
abstractor_abstraction_group = Abstractor::AbstractorAbstractionGroup.
|
102
|
+
abstractor_abstraction_group = Abstractor::AbstractorAbstractionGroup.new(abstractor_subject_group: abstractor_subject_group, about: self)
|
102
103
|
end
|
103
104
|
abstractor_abstraction_group
|
104
105
|
end
|
105
106
|
|
107
|
+
##
|
108
|
+
# Determines if provided abstractor_subject_group reached number of abstractor_abstraction_groups defined by abstractor_subject_group cardinality
|
109
|
+
#
|
110
|
+
# @param [Integer] abstractor_subject_group_id the id of abstractor_subject_group of interest.
|
111
|
+
# @option options [String] :namespace_type the type parameter of the namespace.
|
112
|
+
# @option options [Integer] :namespace_id the instance parameter of the namespace.
|
113
|
+
# @return [boolean]
|
114
|
+
def abstractor_subject_group_complete?(abstractor_subject_group_id, options = {})
|
115
|
+
abstractor_subject_group = Abstractor::AbstractorSubjectGroup.find(abstractor_subject_group_id)
|
116
|
+
if abstractor_subject_group.cardinality.blank?
|
117
|
+
false
|
118
|
+
else
|
119
|
+
options = { namespace_type: nil, namespace_id: nil, abstractor_subject_group_id: abstractor_subject_group_id }.merge(options)
|
120
|
+
abstractor_abstraction_groups = abstractor_abstraction_groups_by_namespace(options)
|
121
|
+
abstractor_abstraction_groups.length == abstractor_subject_group.cardinality
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
106
125
|
##
|
107
126
|
# Returns all abstraction for the abstractable entity by abstractor_abstraction_status:
|
108
127
|
#
|
data/lib/abstractor/enum.rb
CHANGED
@@ -7,5 +7,8 @@ module Abstractor
|
|
7
7
|
ABSTRACTION_STATUS_NEEDS_REVIEW = 'needs review'
|
8
8
|
ABSTRACTION_STATUS_REVIEWED = 'reviewed'
|
9
9
|
ABSTRACTION_STATUSES = [ABSTRACTION_STATUS_NEEDS_REVIEW, ABSTRACTION_STATUS_REVIEWED]
|
10
|
+
|
11
|
+
ABSTRACTOR_SECTION_TYPE_CUSTOM = 'custom'
|
12
|
+
ABSTRACTOR_SECTION_TYPE_NAME_VALUE = 'name/value'
|
10
13
|
end
|
11
14
|
end
|
@@ -8,16 +8,25 @@ module Abstractor
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def create
|
11
|
-
@abstractor_abstraction_group = Abstractor::AbstractorAbstractionGroup.
|
12
|
-
|
11
|
+
@abstractor_abstraction_group = Abstractor::AbstractorAbstractionGroup.new(abstractor_subject_group_id: params[:abstractor_subject_group_id], about_type: params[:about_type], about_id: params[:about_id])
|
12
|
+
|
13
|
+
abstractor_subjects = @abstractor_abstraction_group.abstractor_subject_group.abstractor_subjects
|
14
|
+
unless params[:namespace_type].blank? || params[:namespace_id].blank?
|
15
|
+
@namespace_id = params[:namespace_id]
|
16
|
+
@namespace_type = params[:namespace_type]
|
17
|
+
abstractor_subjects = abstractor_subjects.where(namespace_type: @namespace_type, namespace_id: @namespace_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
abstractor_subjects.each do |abstractor_subject|
|
13
21
|
abstraction = abstractor_subject.abstractor_abstractions.build(about_id: params[:about_id], about_type: params[:about_type])
|
14
|
-
abstraction.build_abstractor_abstraction_group_member(abstractor_abstraction_group: @abstractor_abstraction_group)
|
15
22
|
abstraction.abstractor_subject.abstractor_abstraction_sources.select { |s| s.abstractor_abstraction_source_type.name == 'indirect' }.each do |abstractor_abstraction_source|
|
16
23
|
source = abstractor_subject.subject_type.constantize.find(params[:about_id]).send(abstractor_abstraction_source.from_method)
|
17
24
|
abstraction.abstractor_indirect_sources.build(abstractor_abstraction_source: abstractor_abstraction_source, source_type: source[:source_type], source_method: source[:source_method])
|
25
|
+
|
18
26
|
end
|
19
|
-
abstraction
|
27
|
+
@abstractor_abstraction_group.abstractor_abstractions << abstraction
|
20
28
|
end
|
29
|
+
@abstractor_abstraction_group.save!
|
21
30
|
|
22
31
|
respond_to do |format|
|
23
32
|
format.html { render action: "edit", layout: false }
|
@@ -22,6 +22,8 @@ module Abstractor
|
|
22
22
|
|
23
23
|
base.send :belongs_to, :about, polymorphic: true
|
24
24
|
|
25
|
+
base.send :validates_associated, :abstractor_subject
|
26
|
+
|
25
27
|
# base.send :attr_accessible, :about, :abstractor_subject, :abstractor_subject_id, :value, :about_type, :about_id, :unknown, :not_applicable, :deleted_at, :abstractor_indirect_sources_attributes
|
26
28
|
|
27
29
|
# Hooks
|
@@ -15,25 +15,43 @@ module Abstractor
|
|
15
15
|
# base.send :attr_accessible, :abstractor_subject_group, :abstractor_subject_group_id, :deleted_at, :about, :about_type, :about_id
|
16
16
|
|
17
17
|
# Hooks
|
18
|
+
base.send :validate, :validate_subject_group_cardinality
|
19
|
+
base.send :validate, :must_have_members
|
20
|
+
|
18
21
|
base.send :after_commit, :update_abstractor_abstraction_group_members, :on => :update, :if => Proc.new { |record| record.previous_changes.include?('deleted_at') }
|
19
|
-
end
|
20
22
|
|
21
|
-
|
22
|
-
# Determines if the group can be removed.
|
23
|
-
#
|
24
|
-
# @return [Boolean]
|
25
|
-
def removable?
|
26
|
-
abstractor_abstractions.map(&:abstractor_suggestions).flatten.empty?
|
23
|
+
base.send(:include, InstanceMethods)
|
27
24
|
end
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
module InstanceMethods
|
27
|
+
##
|
28
|
+
# Determines if the group can be removed.
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
31
|
+
def removable?
|
32
|
+
abstractor_abstractions.map(&:abstractor_suggestions).flatten.empty?
|
36
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def update_abstractor_abstraction_group_members
|
37
|
+
return unless deleted?
|
38
|
+
abstractor_abstraction_group_members.each do |gm|
|
39
|
+
gm.soft_delete!
|
40
|
+
gm.abstractor_abstraction.soft_delete!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def must_have_members
|
45
|
+
if self.abstractor_abstraction_group_members.empty? || self.abstractor_abstraction_group_members.all? {|abstractor_abstraction_group_member| abstractor_abstraction_group_member.marked_for_destruction? }
|
46
|
+
errors.add(:base, 'Must have at least one abstractor_abstraction_group_member')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_subject_group_cardinality
|
51
|
+
return if self.abstractor_subject_group.cardinality.blank? || self.persisted?
|
52
|
+
errors.add(:base,"Subject group reached maximum number of abstraction groups (#{abstractor_subject_group.cardinality})") if self.about.abstractor_subject_group_complete?(self.abstractor_subject_group_id)
|
53
|
+
end
|
54
|
+
end
|
37
55
|
end
|
38
56
|
end
|
39
57
|
end
|
@@ -9,6 +9,8 @@ module Abstractor
|
|
9
9
|
base.send :belongs_to, :abstractor_abstraction_group
|
10
10
|
base.send :belongs_to, :abstractor_abstraction
|
11
11
|
|
12
|
+
base.send :validates_associated, :abstractor_abstraction
|
13
|
+
|
12
14
|
# base.send :attr_accessible, :abstractor_abstraction_group, :abstractor_abstraction_group_id, :abstractor_abstraction, :abstractor_abstraction_id, :deleted_at
|
13
15
|
end
|
14
16
|
end
|
@@ -9,11 +9,41 @@ module Abstractor
|
|
9
9
|
base.send :belongs_to, :abstractor_subject
|
10
10
|
base.send :belongs_to, :abstractor_rule_type
|
11
11
|
base.send :belongs_to, :abstractor_abstraction_source_type
|
12
|
+
base.send :belongs_to, :abstractor_abstraction_source_section_type
|
12
13
|
base.send :has_many, :abstractor_suggestion_sources
|
13
14
|
base.send :has_many, :abstractor_abstractions, :through => :abstractor_suggestion_sources
|
14
15
|
base.send :has_many, :abstractor_indirect_sources
|
16
|
+
base.send :has_many, :abstractor_abstraction_source_section_name_variants
|
15
17
|
|
16
|
-
|
18
|
+
def base.abstractor_text(source)
|
19
|
+
text = source[:source_type].find(source[:source_id]).send(source[:source_method])
|
20
|
+
if !source[:section_name].blank?
|
21
|
+
abstractor_section = Abstractor::AbstractorSection.where(source_type: source[:source_type], source_method: source[:source_method], name: source[:section_name]).first
|
22
|
+
if text =~ prepare_section_regular_expression(abstractor_section)
|
23
|
+
text = $2
|
24
|
+
else
|
25
|
+
if abstractor_section.return_note_on_empty_section
|
26
|
+
text = text
|
27
|
+
else
|
28
|
+
text = ''
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
text
|
34
|
+
end
|
35
|
+
|
36
|
+
def base.prepare_section_regular_expression(abstractor_section)
|
37
|
+
regular_expression = nil
|
38
|
+
if abstractor_section.abstractor_section_type.name == Abstractor::Enum::ABSTRACTOR_SECTION_TYPE_CUSTOM
|
39
|
+
regular_expression = abstractor_section.custom_regular_expression
|
40
|
+
else
|
41
|
+
regular_expression = abstractor_section.abstractor_section_type.regular_expression
|
42
|
+
end
|
43
|
+
regular_expression.gsub!('section_name_variants', abstractor_section.prepare_section_name_variants)
|
44
|
+
regular_expression.gsub!('delimiter', abstractor_section.delimiter)
|
45
|
+
Regexp.new(regular_expression, Regexp::IGNORECASE)
|
46
|
+
end
|
17
47
|
end
|
18
48
|
|
19
49
|
def normalize_from_method_to_sources(about)
|
@@ -21,7 +51,7 @@ module Abstractor
|
|
21
51
|
fm = nil
|
22
52
|
fm = about.send(from_method) unless from_method.blank?
|
23
53
|
if fm.is_a?(String) || fm.nil?
|
24
|
-
sources = [{ source_type: about.class , source_id: about.id , source_method: from_method }]
|
54
|
+
sources = [{ source_type: about.class , source_id: about.id , source_method: from_method, section_name: section_name }]
|
25
55
|
else
|
26
56
|
sources = fm
|
27
57
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Abstractor
|
2
|
+
module Methods
|
3
|
+
module Models
|
4
|
+
module AbstractorSection
|
5
|
+
def self.included(base)
|
6
|
+
base.send :include, SoftDelete
|
7
|
+
|
8
|
+
# Associations
|
9
|
+
base.send :belongs_to, :abstractor_section_type
|
10
|
+
base.send :has_many, :abstractor_section_name_variants
|
11
|
+
end
|
12
|
+
|
13
|
+
def prepare_section_name_variants
|
14
|
+
section_name_variants.join('|')
|
15
|
+
end
|
16
|
+
|
17
|
+
def section_name_variants
|
18
|
+
[name].concat(abstractor_section_name_variants.map(&:name))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -129,7 +129,7 @@ module Abstractor
|
|
129
129
|
def abstract_custom_suggestion(about, abstractor_abstraction, abstractor_abstraction_source)
|
130
130
|
suggestions = about.send(abstractor_abstraction_source.custom_method)
|
131
131
|
suggestions.each do |suggestion|
|
132
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, nil, nil, about.id, about.class.to_s, abstractor_abstraction_source.from_method, suggestion[:suggestion], nil, nil, abstractor_abstraction_source.custom_method, suggestion[:explanation])
|
132
|
+
suggest(abstractor_abstraction, abstractor_abstraction_source, nil, nil, about.id, about.class.to_s, abstractor_abstraction_source.from_method, abstractor_abstraction_source.section_name, suggestion[:suggestion], nil, nil, abstractor_abstraction_source.custom_method, suggestion[:explanation])
|
133
133
|
end
|
134
134
|
create_unknown_abstractor_suggestion(about, abstractor_abstraction, abstractor_abstraction_source)
|
135
135
|
end
|
@@ -145,7 +145,7 @@ module Abstractor
|
|
145
145
|
|
146
146
|
def abstract_sentential_value(about, abstractor_abstraction, abstractor_abstraction_source)
|
147
147
|
abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
|
148
|
-
abstractor_text =
|
148
|
+
abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
149
149
|
abstractor_object_value_ids = abstractor_abstraction_schema.abstractor_object_values.map(&:id)
|
150
150
|
|
151
151
|
abstractor_object_values = []
|
@@ -187,7 +187,7 @@ module Abstractor
|
|
187
187
|
Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], object_variant)
|
188
188
|
)
|
189
189
|
if !reject
|
190
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, object_variant.downcase, sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], abstractor_object_value, nil, nil, nil, nil)
|
190
|
+
suggest(abstractor_abstraction, abstractor_abstraction_source, object_variant.downcase, sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], abstractor_object_value, nil, nil, nil, nil)
|
191
191
|
end
|
192
192
|
end
|
193
193
|
end
|
@@ -206,7 +206,7 @@ module Abstractor
|
|
206
206
|
|
207
207
|
def abstract_canonical_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
|
208
208
|
abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
|
209
|
-
abstractor_text =
|
209
|
+
abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
210
210
|
parser = Abstractor::Parser.new(abstractor_text)
|
211
211
|
abstractor_abstraction_schema.predicate_variants.each do |predicate_variant|
|
212
212
|
abstractor_abstraction_schema.abstractor_object_values.each do |abstractor_object_value|
|
@@ -214,13 +214,13 @@ module Abstractor
|
|
214
214
|
match_value = "#{Regexp.escape(predicate_variant)}:\s*#{Regexp.escape(object_variant)}"
|
215
215
|
matches = parser.scan(match_value, word_boundary: true).uniq
|
216
216
|
matches.each do |match|
|
217
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, match, match, source[:source_id], source[:source_type].to_s, source[:source_method], abstractor_object_value, nil, nil, nil, nil)
|
217
|
+
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)
|
218
218
|
end
|
219
219
|
|
220
220
|
match_value = "#{Regexp.escape(predicate_variant)}#{Regexp.escape(object_variant)}"
|
221
221
|
matches = parser.scan(match_value, word_boundary: true).uniq
|
222
222
|
matches.each do |match|
|
223
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, match, match, source[:source_id], source[:source_type].to_s, source[:source_method], abstractor_object_value, nil, nil, nil, nil)
|
223
|
+
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)
|
224
224
|
end
|
225
225
|
end
|
226
226
|
end
|
@@ -230,7 +230,7 @@ module Abstractor
|
|
230
230
|
|
231
231
|
def abstract_sentential_name_value(about, abstractor_abstraction, abstractor_abstraction_source)
|
232
232
|
abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
|
233
|
-
abstractor_text =
|
233
|
+
abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
234
234
|
parser = Abstractor::Parser.new(abstractor_text)
|
235
235
|
abstractor_abstraction_schema.predicate_variants.each do |predicate_variant|
|
236
236
|
ranges = parser.range_all(Regexp.escape(predicate_variant))
|
@@ -250,7 +250,7 @@ module Abstractor
|
|
250
250
|
Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], object_variant)
|
251
251
|
)
|
252
252
|
if !reject
|
253
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, sentence[:sentence], sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], abstractor_object_value, nil, nil, nil, nil)
|
253
|
+
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)
|
254
254
|
end
|
255
255
|
end
|
256
256
|
end
|
@@ -262,7 +262,7 @@ module Abstractor
|
|
262
262
|
end
|
263
263
|
end
|
264
264
|
|
265
|
-
def suggest(abstractor_abstraction, abstractor_abstraction_source, match_value, sentence_match_value, source_id, source_type, source_method, suggested_value, unknown, not_applicable, custom_method, custom_explanation)
|
265
|
+
def suggest(abstractor_abstraction, abstractor_abstraction_source, match_value, sentence_match_value, source_id, source_type, source_method, section_name, suggested_value, unknown, not_applicable, custom_method, custom_explanation)
|
266
266
|
match_value.strip! unless match_value.nil?
|
267
267
|
sentence_match_value.strip! unless sentence_match_value.nil?
|
268
268
|
if abstractor_object_value?(suggested_value)
|
@@ -283,7 +283,7 @@ module Abstractor
|
|
283
283
|
abstractor_suggestion.abstractor_suggestion_object_value = Abstractor::AbstractorSuggestionObjectValue.new(abstractor_object_value: abstractor_object_value) if abstractor_object_value
|
284
284
|
end
|
285
285
|
|
286
|
-
abstractor_suggestion_source = abstractor_suggestion.detect_abstractor_suggestion_source(abstractor_abstraction_source, sentence_match_value, source_id, source_type, source_method)
|
286
|
+
abstractor_suggestion_source = abstractor_suggestion.detect_abstractor_suggestion_source(abstractor_abstraction_source, sentence_match_value, source_id, source_type, source_method, section_name)
|
287
287
|
if !abstractor_suggestion_source
|
288
288
|
Abstractor::AbstractorSuggestionSource.create(
|
289
289
|
abstractor_abstraction_source: abstractor_abstraction_source,
|
@@ -293,6 +293,7 @@ module Abstractor
|
|
293
293
|
source_id: source_id,
|
294
294
|
source_type: source_type,
|
295
295
|
source_method: source_method,
|
296
|
+
section_name: section_name,
|
296
297
|
custom_method: custom_method,
|
297
298
|
custom_explanation: custom_explanation
|
298
299
|
)
|
@@ -306,7 +307,7 @@ module Abstractor
|
|
306
307
|
|
307
308
|
def create_unknown_abstractor_suggestion_name_only(about, abstractor_abstraction, abstractor_abstraction_source)
|
308
309
|
abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
|
309
|
-
abstractor_text =
|
310
|
+
abstractor_text = Abstractor::AbstractorAbstractionSource.abstractor_text(source)
|
310
311
|
parser = Abstractor::Parser.new(abstractor_text)
|
311
312
|
#Create an 'unknown' suggestion based on match name only if we have not made a suggstion
|
312
313
|
if abstractor_abstraction.abstractor_suggestions(true).empty?
|
@@ -322,7 +323,7 @@ module Abstractor
|
|
322
323
|
Abstractor::NegationDetection.manual_negated_match_value?(sentence[:sentence], predicate_variant)
|
323
324
|
)
|
324
325
|
if !reject
|
325
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, predicate_variant.downcase, sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], nil, true, nil, nil, nil)
|
326
|
+
suggest(abstractor_abstraction, abstractor_abstraction_source, predicate_variant.downcase, sentence[:sentence], source[:source_id], source[:source_type].to_s, source[:source_method], source[:section_name], nil, true, nil, nil, nil)
|
326
327
|
end
|
327
328
|
end
|
328
329
|
end
|
@@ -336,7 +337,7 @@ module Abstractor
|
|
336
337
|
#Create an 'unknown' suggestion based on matching nothing only if we have not made a suggstion
|
337
338
|
abstractor_abstraction_source.normalize_from_method_to_sources(about).each do |source|
|
338
339
|
if abstractor_abstraction.abstractor_suggestions(true).select { |abstractor_suggestion| abstractor_suggestion.unknown != true }.empty?
|
339
|
-
suggest(abstractor_abstraction, abstractor_abstraction_source, nil, nil, source[:source_id], source[:source_type].to_s, source[:source_method],
|
340
|
+
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)
|
340
341
|
end
|
341
342
|
end
|
342
343
|
end
|
@@ -12,6 +12,8 @@ module Abstractor
|
|
12
12
|
base.send :has_many, :abstractor_abstractions, :through => :abstractor_abstraction_groups
|
13
13
|
|
14
14
|
# base.send :attr_accessible, :deleted_at, :name
|
15
|
+
# Validations
|
16
|
+
base.send :validates, :cardinality, numericality: { only_integer: true, greater_than: 0 }, unless: Proc.new { |a| a.cardinality.blank? }
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -74,13 +74,14 @@ module Abstractor
|
|
74
74
|
abstractor_abstraction.abstractor_suggestions.where('id != ?', id)
|
75
75
|
end
|
76
76
|
|
77
|
-
def detect_abstractor_suggestion_source(abstractor_abstraction_source, sentence_match_value, source_id, source_type, source_method)
|
77
|
+
def detect_abstractor_suggestion_source(abstractor_abstraction_source, sentence_match_value, source_id, source_type, source_method, section_name)
|
78
78
|
abstractor_suggestion_source = abstractor_suggestion_sources.detect do |abstractor_suggestion_source|
|
79
79
|
abstractor_suggestion_source.abstractor_abstraction_source == abstractor_abstraction_source &&
|
80
80
|
abstractor_suggestion_source.sentence_match_value == sentence_match_value &&
|
81
81
|
abstractor_suggestion_source.source_id == source_id &&
|
82
82
|
abstractor_suggestion_source.source_type == source_type &&
|
83
|
-
abstractor_suggestion_source.source_method == source_method
|
83
|
+
abstractor_suggestion_source.source_method == source_method &&
|
84
|
+
abstractor_suggestion_source.section_name == section_name
|
84
85
|
end
|
85
86
|
end
|
86
87
|
end
|
data/lib/abstractor/setup.rb
CHANGED
@@ -28,6 +28,10 @@ module Abstractor
|
|
28
28
|
Abstractor::AbstractorAbstractionSourceType.where(name: 'nlp suggestion').first_or_create
|
29
29
|
Abstractor::AbstractorAbstractionSourceType.where(name: 'custom suggestion').first_or_create
|
30
30
|
Abstractor::AbstractorAbstractionSourceType.where(name: 'indirect').first_or_create
|
31
|
+
|
32
|
+
puts 'Setting up Abstractor::AbstractorSectionType'
|
33
|
+
Abstractor::AbstractorSectionType.where(name: Abstractor::Enum::ABSTRACTOR_SECTION_TYPE_CUSTOM).first_or_create
|
34
|
+
Abstractor::AbstractorSectionType.where(name: Abstractor::Enum::ABSTRACTOR_SECTION_TYPE_NAME_VALUE, regular_expression: "(?<=^|[\r\n])(section_name_variants)[\s]*delimiter([^\r\n]*(?:[\r\n]+(?![A-Z].*delimiter).*)*)").first_or_create
|
31
35
|
end
|
32
36
|
end
|
33
37
|
end
|
data/lib/abstractor/version.rb
CHANGED
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.0
|
4
|
+
version: 4.1.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: 2014-
|
11
|
+
date: 2014-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -465,6 +465,9 @@ files:
|
|
465
465
|
- app/models/abstractor/abstractor_object_value_variant.rb
|
466
466
|
- app/models/abstractor/abstractor_relation_type.rb
|
467
467
|
- app/models/abstractor/abstractor_rule_type.rb
|
468
|
+
- app/models/abstractor/abstractor_section.rb
|
469
|
+
- app/models/abstractor/abstractor_section_name_variant.rb
|
470
|
+
- app/models/abstractor/abstractor_section_type.rb
|
468
471
|
- app/models/abstractor/abstractor_subject.rb
|
469
472
|
- app/models/abstractor/abstractor_subject_group.rb
|
470
473
|
- app/models/abstractor/abstractor_subject_group_member.rb
|
@@ -512,6 +515,8 @@ files:
|
|
512
515
|
- db/migrate/20140718014952_refactor_abstractor_rule_types.rb
|
513
516
|
- db/migrate/20140803205149_add_custom_explanation_to_abstractor_suggestion_sources.rb
|
514
517
|
- db/migrate/20140816005228_add_namespace_to_abstractor_subjects.rb
|
518
|
+
- db/migrate/20141028020332_add_cardinality_to_abstractor_subject_group.rb
|
519
|
+
- db/migrate/20141107171413_add_sectioning.rb
|
515
520
|
- db/seeds.rb
|
516
521
|
- lib/abstractor.rb
|
517
522
|
- lib/abstractor/abstractable.rb
|
@@ -536,6 +541,9 @@ files:
|
|
536
541
|
- lib/abstractor/methods/models/abstractor_object_value_variant.rb
|
537
542
|
- lib/abstractor/methods/models/abstractor_relation_type.rb
|
538
543
|
- lib/abstractor/methods/models/abstractor_rule_type.rb
|
544
|
+
- lib/abstractor/methods/models/abstractor_section.rb
|
545
|
+
- lib/abstractor/methods/models/abstractor_section_name_variant.rb
|
546
|
+
- lib/abstractor/methods/models/abstractor_section_type.rb
|
539
547
|
- lib/abstractor/methods/models/abstractor_subject.rb
|
540
548
|
- lib/abstractor/methods/models/abstractor_subject_group.rb
|
541
549
|
- lib/abstractor/methods/models/abstractor_subject_group_member.rb
|