discerner 1.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +97 -0
  4. data/Rakefile +29 -0
  5. data/app/assets/images/discerner/add.png +0 -0
  6. data/app/assets/images/discerner/ajax-loader.gif +0 -0
  7. data/app/assets/images/discerner/bar.gif +0 -0
  8. data/app/assets/images/discerner/bullet_arrow_down.png +0 -0
  9. data/app/assets/images/discerner/bullet_arrow_up.png +0 -0
  10. data/app/assets/images/discerner/cog.png +0 -0
  11. data/app/assets/images/discerner/delete.png +0 -0
  12. data/app/assets/images/discerner/edit.png +0 -0
  13. data/app/assets/images/discerner/excel.png +0 -0
  14. data/app/assets/images/discerner/greencheck.gif +0 -0
  15. data/app/assets/images/discerner/rails.png +0 -0
  16. data/app/assets/images/discerner/show.png +0 -0
  17. data/app/assets/images/discerner/switch_minus.gif +0 -0
  18. data/app/assets/images/discerner/switch_plus.gif +0 -0
  19. data/app/assets/javascripts/discerner/application.js +20 -0
  20. data/app/assets/javascripts/discerner/combobox.js +301 -0
  21. data/app/assets/javascripts/discerner/discerner.js +19 -0
  22. data/app/assets/javascripts/discerner/export_parameters.js +13 -0
  23. data/app/assets/javascripts/discerner/jquery/jquery.blockUI.js +576 -0
  24. data/app/assets/javascripts/discerner/jquery/jquery.form.js +1074 -0
  25. data/app/assets/javascripts/discerner/nested_attributes.js +69 -0
  26. data/app/assets/javascripts/discerner/search_combinations.js +49 -0
  27. data/app/assets/javascripts/discerner/search_parameter.js +131 -0
  28. data/app/assets/javascripts/discerner/search_parameter_value.js +172 -0
  29. data/app/assets/javascripts/discerner/searches.js +93 -0
  30. data/app/assets/javascripts/discerner/url.js +42 -0
  31. data/app/assets/stylesheets/discerner/application.css +16 -0
  32. data/app/assets/stylesheets/discerner/buttons.sass +13 -0
  33. data/app/assets/stylesheets/discerner/categorized_autocompleter.sass +53 -0
  34. data/app/assets/stylesheets/discerner/discerner.sass +51 -0
  35. data/app/assets/stylesheets/discerner/export_parameters.sass +43 -0
  36. data/app/assets/stylesheets/discerner/links.sass +29 -0
  37. data/app/assets/stylesheets/discerner/searches.sass +205 -0
  38. data/app/assets/stylesheets/discerner/tables.sass +32 -0
  39. data/app/controllers/discerner/application_controller.rb +2 -0
  40. data/app/controllers/discerner/export_parameters_controller.rb +5 -0
  41. data/app/controllers/discerner/parameters_controller.rb +5 -0
  42. data/app/controllers/discerner/searches_controller.rb +5 -0
  43. data/app/helpers/discerner/application_helper.rb +4 -0
  44. data/app/helpers/discerner/parameters_helper.rb +5 -0
  45. data/app/helpers/discerner/searches_helper.rb +5 -0
  46. data/app/models/discerner/dictionary.rb +5 -0
  47. data/app/models/discerner/export_parameter.rb +5 -0
  48. data/app/models/discerner/operator.rb +5 -0
  49. data/app/models/discerner/parameter.rb +5 -0
  50. data/app/models/discerner/parameter_category.rb +5 -0
  51. data/app/models/discerner/parameter_type.rb +5 -0
  52. data/app/models/discerner/parameter_value.rb +5 -0
  53. data/app/models/discerner/parameter_value_categorization.rb +5 -0
  54. data/app/models/discerner/parameter_value_category.rb +5 -0
  55. data/app/models/discerner/search.rb +5 -0
  56. data/app/models/discerner/search_combination.rb +5 -0
  57. data/app/models/discerner/search_parameter.rb +5 -0
  58. data/app/models/discerner/search_parameter_value.rb +5 -0
  59. data/app/views/discerner/export_parameters/index.html.haml +55 -0
  60. data/app/views/discerner/parameters/_values_autocompleter.html.haml +49 -0
  61. data/app/views/discerner/parameters/values.html.haml +1 -0
  62. data/app/views/discerner/searches/_form.html.haml +21 -0
  63. data/app/views/discerner/searches/_form_combined_searches.html.haml +32 -0
  64. data/app/views/discerner/searches/_form_controls.html.haml +8 -0
  65. data/app/views/discerner/searches/_form_header.html.haml +39 -0
  66. data/app/views/discerner/searches/_form_search_parameters.html.haml +28 -0
  67. data/app/views/discerner/searches/_list.html.haml +17 -0
  68. data/app/views/discerner/searches/_search_combination_fields.html.haml +22 -0
  69. data/app/views/discerner/searches/_search_parameter_fields.html.haml +48 -0
  70. data/app/views/discerner/searches/_search_parameter_value_fields.html.haml +62 -0
  71. data/app/views/discerner/searches/_summary.html.haml +25 -0
  72. data/app/views/discerner/searches/edit.html.haml +8 -0
  73. data/app/views/discerner/searches/index.html.haml +13 -0
  74. data/app/views/discerner/searches/index.js.haml +1 -0
  75. data/app/views/discerner/searches/new.html.haml +3 -0
  76. data/app/views/discerner/searches/rename.html.haml +6 -0
  77. data/app/views/discerner/searches/update.js.haml +7 -0
  78. data/app/views/discerner/shared/_categorized_autocompleter_items.html.haml +15 -0
  79. data/app/views/discerner/shared/_error_messages.html.haml +5 -0
  80. data/app/views/layouts/discerner/searches.html.erb +17 -0
  81. data/config/cucumber.yml +8 -0
  82. data/config/routes.rb +17 -0
  83. data/db/migrate/20121004040716_create_discerner_dictionaries.rb +11 -0
  84. data/db/migrate/20121004153043_create_discerner_parameter_categories.rb +12 -0
  85. data/db/migrate/20121005194843_create_discerner_parameter_types.rb +11 -0
  86. data/db/migrate/20121005203223_create_discerner_parameters.rb +14 -0
  87. data/db/migrate/20121008154855_create_discerner_operators.rb +13 -0
  88. data/db/migrate/20121008160313_create_discerner_operators_parameter_types.rb +8 -0
  89. data/db/migrate/20121008161455_create_discerner_parameter_values.rb +13 -0
  90. data/db/migrate/20121008180829_create_discerner_searches.rb +11 -0
  91. data/db/migrate/20121008182443_create_discerner_search_parameters.rb +11 -0
  92. data/db/migrate/20121011205130_create_discerner_search_parameter_values.rb +15 -0
  93. data/db/migrate/20121211213215_add_dictionary_id_to_discerner_searches.rb +5 -0
  94. data/db/migrate/20130205193602_create_discerner_search_combinations.rb +12 -0
  95. data/db/migrate/20130211230636_create_discerner_export_parameters.rb +9 -0
  96. data/db/migrate/20130213185818_add_search_columns_to_discerner_parameters.rb +38 -0
  97. data/db/migrate/20130213205255_rename_database_name_to_search_value_in_discerner_parameter_values.rb +5 -0
  98. data/db/migrate/20130215165416_add_searchable_to_discerner_parameters.rb +5 -0
  99. data/db/migrate/20130218230257_add_exclusive_to_discerner_parameters.rb +5 -0
  100. data/db/migrate/20130220163015_replace_integer_type_with_numeric.rb +22 -0
  101. data/db/migrate/20130221172826_add_unique_identifier_to_discerner_parameters.rb +5 -0
  102. data/db/migrate/20130222052924_change_search_attribute_to_method.rb +29 -0
  103. data/db/migrate/20130222070959_add_export_columns_to_discerner_parameters.rb +6 -0
  104. data/db/migrate/20130227031747_add_unique_identifier_to_discerner_operators.rb +16 -0
  105. data/db/migrate/20130306015019_change_discerner_parameter_values_name.rb +9 -0
  106. data/db/migrate/20130306212430_add_deleted_at_to_discerner_search_parameters.rb +5 -0
  107. data/db/migrate/20130306212504_add_deleted_at_to_discerner_search_parameter_values.rb +5 -0
  108. data/db/migrate/20130306212527_add_deleted_at_to_discerner_search_combinations.rb +5 -0
  109. data/db/migrate/20130306212818_add_deleted_at_to_discerner_export_parameters.rb +5 -0
  110. data/db/migrate/20130311190717_add_operator_type_to_discerner_operators.rb +5 -0
  111. data/db/migrate/20131212175110_remove_extra_search_parameter_values.rb +10 -0
  112. data/db/migrate/20140204170625_create_discerner_parameter_value_categories.rb +16 -0
  113. data/db/migrate/20140204170646_create_discerner_parameter_value_categorizations.rb +12 -0
  114. data/db/migrate/20140227191827_remove_blank_parameter_values_from_export_parameters.rb +10 -0
  115. data/db/seeds.rb +0 -0
  116. data/lib/discerner/engine.rb +16 -0
  117. data/lib/discerner/methods/controllers/export_parameters_controller.rb +38 -0
  118. data/lib/discerner/methods/controllers/parameters_controller.rb +30 -0
  119. data/lib/discerner/methods/controllers/searches_controller.rb +204 -0
  120. data/lib/discerner/methods/helpers/searches_helper.rb +145 -0
  121. data/lib/discerner/methods/models/dictionary.rb +54 -0
  122. data/lib/discerner/methods/models/export_parameter.rb +35 -0
  123. data/lib/discerner/methods/models/operator.rb +42 -0
  124. data/lib/discerner/methods/models/parameter.rb +90 -0
  125. data/lib/discerner/methods/models/parameter_category.rb +60 -0
  126. data/lib/discerner/methods/models/parameter_type.rb +33 -0
  127. data/lib/discerner/methods/models/parameter_value.rb +87 -0
  128. data/lib/discerner/methods/models/parameter_value_categorization.rb +21 -0
  129. data/lib/discerner/methods/models/parameter_value_category.rb +45 -0
  130. data/lib/discerner/methods/models/search.rb +147 -0
  131. data/lib/discerner/methods/models/search_combination.rb +50 -0
  132. data/lib/discerner/methods/models/search_parameter.rb +128 -0
  133. data/lib/discerner/methods/models/search_parameter_value.rb +130 -0
  134. data/lib/discerner/methods/models/soft_delete.rb +35 -0
  135. data/lib/discerner/methods/models/warning.rb +15 -0
  136. data/lib/discerner/parser.rb +497 -0
  137. data/lib/discerner/version.rb +3 -0
  138. data/lib/discerner.rb +4 -0
  139. data/lib/generators/discerner/dictionary/dictionary_generator.rb +38 -0
  140. data/lib/generators/discerner/dictionary/templates/model.rb +15 -0
  141. data/lib/generators/discerner/dictionary/templates/show.xls.erb +37 -0
  142. data/lib/generators/discerner/dictionary/templates/view.html.haml +2 -0
  143. data/lib/generators/discerner/install/install_generator.rb +153 -0
  144. data/lib/generators/discerner/install/templates/controllers/export_parameters_controller.rb +20 -0
  145. data/lib/generators/discerner/install/templates/controllers/parameters_controller.rb +15 -0
  146. data/lib/generators/discerner/install/templates/controllers/searches_controller.rb +39 -0
  147. data/lib/generators/discerner/install/templates/dictionaries.yml +236 -0
  148. data/lib/generators/discerner/install/templates/helpers/searches_helper.rb +9 -0
  149. data/lib/generators/discerner/install/templates/models/book.rb +15 -0
  150. data/lib/generators/discerner/install/templates/models/dictionary.rb +9 -0
  151. data/lib/generators/discerner/install/templates/models/export_parameter.rb +9 -0
  152. data/lib/generators/discerner/install/templates/models/operator.rb +9 -0
  153. data/lib/generators/discerner/install/templates/models/parameter.rb +10 -0
  154. data/lib/generators/discerner/install/templates/models/parameter_category.rb +9 -0
  155. data/lib/generators/discerner/install/templates/models/parameter_type.rb +9 -0
  156. data/lib/generators/discerner/install/templates/models/parameter_value.rb +9 -0
  157. data/lib/generators/discerner/install/templates/models/parameter_value_categorization.rb +9 -0
  158. data/lib/generators/discerner/install/templates/models/parameter_value_category.rb +9 -0
  159. data/lib/generators/discerner/install/templates/models/search.rb +9 -0
  160. data/lib/generators/discerner/install/templates/models/search_combination.rb +9 -0
  161. data/lib/generators/discerner/install/templates/models/search_parameter.rb +9 -0
  162. data/lib/generators/discerner/install/templates/models/search_parameter_value.rb +9 -0
  163. data/lib/generators/discerner/install/templates/views/layouts/searches.html.erb +17 -0
  164. data/lib/setup/operators.yml +91 -0
  165. data/lib/tasks/cucumber.rake +65 -0
  166. data/lib/tasks/discerner_tasks.rake +30 -0
  167. metadata +531 -0
@@ -0,0 +1,29 @@
1
+ class ChangeSearchAttributeToMethod < ActiveRecord::Migration
2
+ class Search < ActiveRecord::Base
3
+ include Discerner::Methods::Models::Parameter
4
+ end
5
+
6
+ def self.up
7
+ add_column :discerner_parameters, :search_method, :string
8
+
9
+ Discerner::Parameter.order(:id).each do |p|
10
+ p.search_method = p.search_attribute
11
+ p.save!
12
+ end
13
+
14
+ remove_index :discerner_parameters, :name => 'index_discerner_parameters'
15
+ remove_column :discerner_parameters, :search_attribute
16
+ end
17
+
18
+ def self.down
19
+ add_column :discerner_parameters, :search_attribute, :string
20
+
21
+ Discerner::Parameter.order(:id).each do |p|
22
+ p.search_attribute = p.search_method
23
+ p.save!
24
+ end
25
+
26
+ remove_column :discerner_parameters, :search_method
27
+ add_index :discerner_parameters, [:search_model, :search_attribute, :parameter_category_id, :deleted_at], :unique => true, :name => 'index_discerner_parameters'
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ class AddExportColumnsToDiscernerParameters < ActiveRecord::Migration
2
+ def change
3
+ add_column :discerner_parameters, :export_model, :string
4
+ add_column :discerner_parameters, :export_method, :string
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ class AddUniqueIdentifierToDiscernerOperators < ActiveRecord::Migration
2
+ class Operator < ActiveRecord::Base
3
+ include Discerner::Methods::Models::Operator
4
+ end
5
+
6
+ def change
7
+ add_column :discerner_operators, :unique_identifier, :string
8
+
9
+ Discerner::Operator.order(:id).each do |p|
10
+ p.unique_identifier = p.text.parameterize.underscore
11
+ p.save!
12
+ end
13
+ remove_index :discerner_operators, :name => 'index_discerner_operators'
14
+ add_index :discerner_operators, [:unique_identifier, :deleted_at], :unique => true, :name => 'index_discerner_operators'
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ class ChangeDiscernerParameterValuesName < ActiveRecord::Migration
2
+ def up
3
+ change_column :discerner_parameter_values, :name, :string, :limit => 1000
4
+ end
5
+
6
+ def down
7
+ change_column :discerner_parameter_values, :name, :string, :limit => 255
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class AddDeletedAtToDiscernerSearchParameters < ActiveRecord::Migration
2
+ def change
3
+ add_column :discerner_search_parameters, :deleted_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddDeletedAtToDiscernerSearchParameterValues < ActiveRecord::Migration
2
+ def change
3
+ add_column :discerner_search_parameter_values, :deleted_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddDeletedAtToDiscernerSearchCombinations < ActiveRecord::Migration
2
+ def change
3
+ add_column :discerner_search_combinations, :deleted_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddDeletedAtToDiscernerExportParameters < ActiveRecord::Migration
2
+ def change
3
+ add_column :discerner_export_parameters, :deleted_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddOperatorTypeToDiscernerOperators < ActiveRecord::Migration
2
+ def change
3
+ add_column :discerner_operators, :operator_type, :string
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class RemoveExtraSearchParameterValues < ActiveRecord::Migration
2
+ def up
3
+ sql = Discerner::SearchParameterValue.joins(:search_parameter => {:parameter => :parameter_type}).where("discerner_parameter_types.name = 'combobox' and chosen is null").to_sql
4
+ search_parameter_values_array = Discerner::SearchParameterValue.find_by_sql(sql)
5
+ search_parameter_values_array.each{|r| r.delete}
6
+ end
7
+
8
+ def down
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ class CreateDiscernerParameterValueCategories < ActiveRecord::Migration
2
+ def change
3
+ create_table :discerner_parameter_value_categories do |t|
4
+ t.integer :parameter_id
5
+ t.string :name
6
+ t.string :unique_identifier
7
+ t.integer :display_order
8
+ t.datetime :deleted_at
9
+ t.boolean :collapse
10
+
11
+ t.timestamps
12
+ end
13
+
14
+ add_index :discerner_parameter_value_categories, [:parameter_id, :unique_identifier, :deleted_at], :unique => true, :name => 'discerner_parameter_value_categories_uniq_index'
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ class CreateDiscernerParameterValueCategorizations < ActiveRecord::Migration
2
+ def change
3
+ create_table :discerner_parameter_value_categorizations do |t|
4
+ t.integer :parameter_value_category_id
5
+ t.integer :parameter_value_id
6
+ t.datetime :deleted_at
7
+
8
+ t.timestamps
9
+ end
10
+ add_index :discerner_parameter_value_categorizations, [:parameter_value_category_id, :parameter_value_id, :deleted_at], :unique => true, :name => 'discerner_parameter_value_categorizations_uniq_index'
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class RemoveBlankParameterValuesFromExportParameters < ActiveRecord::Migration
2
+ def up
3
+ Discerner::Parameter.where(:search_model => nil).each do |p|
4
+ p.parameter_values.destroy_all
5
+ end
6
+ end
7
+
8
+ def down
9
+ end
10
+ end
data/db/seeds.rb ADDED
File without changes
@@ -0,0 +1,16 @@
1
+ require 'haml'
2
+ require 'jquery-rails'
3
+ require 'jquery-ui-rails'
4
+
5
+ module Discerner
6
+ class Engine < ::Rails::Engine
7
+ isolate_namespace Discerner
8
+ root = File.expand_path('../../', __FILE__)
9
+ config.autoload_paths << root
10
+ config.generators do |g|
11
+ g.test_framework :rspec
12
+ g.integration_tool :rspec
13
+ g.template_engine :haml
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ module Discerner
2
+ module Methods
3
+ module Controllers
4
+ module ExportParametersController
5
+ def self.included(base)
6
+ base.send :helper, :all
7
+ base.send :before_filter, :load_search
8
+ base.send :layout, 'layouts/discerner/searches'
9
+ end
10
+
11
+ def index
12
+ if @discerner_search.disabled?
13
+ error_message = "There is an issue with the this export that has to be corrected before it can be executed"
14
+ if @discerner_search.warnings.any?
15
+ error_message << ': '
16
+ error_message << @discerner_search.warnings.full_messages.join(',')
17
+ end
18
+ end
19
+ flash[:error] = error_message unless error_message.blank?
20
+ end
21
+
22
+ def assign
23
+ existing_export_parameters = @discerner_search.export_parameters || []
24
+ export_parameter_ids = params[:parameter_ids] || []
25
+
26
+ existing_export_parameters.map{ |export_parameter| export_parameter.delete unless export_parameter_ids.include?(export_parameter.parameter_id) }
27
+ export_parameter_ids.map{ |parameter_id| @discerner_search.export_parameters.create(:parameter_id => parameter_id) unless existing_export_parameters.where(:parameter_id => parameter_id).any?}
28
+ redirect_to search_path(@discerner_search, :format => 'xls')
29
+ end
30
+
31
+ private
32
+ def load_search
33
+ @discerner_search = Discerner::Search.find(params[:id])
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ module Discerner
2
+ module Methods
3
+ module Controllers
4
+ module ParametersController
5
+ def self.included(base)
6
+ base.send :before_filter, :load_parameter
7
+ end
8
+
9
+ def values
10
+ @parameter_values = @parameter.parameter_values.includes(:parameter_value_category).not_deleted.ordered_by_name
11
+ @search_parameter_value_id = params[:search_parameter_value_id]
12
+ @searchable_parameter_values = {}
13
+ @searchable_parameter_values[@parameter.id] = @parameter_values
14
+ respond_to do |format|
15
+ format.html { render :layout => false }
16
+ format.json { render :text => { :type => @parameter.parameter_type.name,
17
+ :parameter_values => @parameter_values.map { |v| { :parameter_value_id => v.id, :name => v.name } }}.to_json }
18
+ end
19
+ end
20
+
21
+ private
22
+ def load_parameter
23
+ id = params[:id]
24
+ id ||= params[:parameter_id]
25
+ @parameter = Parameter.find(id)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,204 @@
1
+ module Discerner
2
+ module Methods
3
+ module Controllers
4
+ module SearchesController
5
+ def self.included(base)
6
+ base.send :before_filter, :load_search, :only => [:edit, :update, :rename, :destroy, :show]
7
+ end
8
+
9
+ def new
10
+ set_searchable_dictionaries
11
+ if @searchable_dictionaries.any?
12
+ set_searchables
13
+ @discerner_search = Discerner::Search.new
14
+ else
15
+ flash[:error] = 'No searchable dictionaries found. Make sure that dictionaries are loaded.'
16
+ end
17
+ end
18
+
19
+ def create
20
+ @discerner_search = Discerner::Search.new(params[:search])
21
+ @discerner_search.username = discerner_user.username unless discerner_user.blank?
22
+
23
+ set_searchable_dictionaries
24
+ set_searchables
25
+ respond_to do |format|
26
+ if @discerner_search.save
27
+ format.html { redirect_to(edit_search_path(@discerner_search)) }
28
+ else
29
+ format.html { render :action => "new" }
30
+ end
31
+ end
32
+ end
33
+
34
+ def edit
35
+ set_searchable_dictionaries
36
+ set_searchables
37
+
38
+ if @discerner_search.disabled?
39
+ error_message = "There is an issue with the this search that has to be corrected before it can be executed"
40
+ if @discerner_search.warnings.any?
41
+ error_message << ': '
42
+ error_message << @discerner_search.warnings.full_messages.join(',')
43
+ end
44
+ else
45
+ if dictionary_model
46
+ dictionary = dictionary_model.new(@discerner_search)
47
+ if dictionary.respond_to?('search')
48
+ @results = dictionary.search(params, dictionary_search_options)
49
+ else
50
+ error_message = "Model '#{dictionary_model_name}' instance does not respond to 'search' method. You need to implement it to be able to run search on this dictionary"
51
+ end
52
+ else
53
+ error_message = "Model '#{dictionary_model_name}' could not be found. You need to create it to be able to run search on this dictionary"
54
+ end
55
+ end
56
+ flash[:error] = error_message unless error_message.blank?
57
+ end
58
+
59
+ def update
60
+ set_searchable_dictionaries
61
+ set_searchables
62
+ respond_to do |format|
63
+ if @discerner_search.update_attributes(params[:search])
64
+ format.html { redirect_to(edit_search_path(@discerner_search), :notice => 'Search was successfully updated.') }
65
+ format.js
66
+ else
67
+ format.html { render :action => "edit" }
68
+ format.js
69
+ end
70
+ end
71
+ end
72
+
73
+ def index
74
+ searches = Discerner::Search.not_deleted.includes(
75
+ :dictionary,
76
+ :export_parameters => [:parameter => [:parameter_type]],
77
+ :search_combinations => [:combined_search => [:search_parameters => [:parameter => [:parameter_type], :search_parameter_values => [:parameter_value]]]],
78
+ :search_parameters => [:parameter => [:parameter_type], :search_parameter_values => [:parameter_value]])
79
+
80
+ username = discerner_user.username unless discerner_user.blank?
81
+ searches = searches.by_user(username) unless username.blank?
82
+
83
+ searches = searches.where('discerner_searches.name like ?', '%' + params[:query] + '%') unless params[:query].blank?
84
+ @discerner_searches = searches.order("discerner_searches.updated_at DESC")
85
+ end
86
+
87
+ def destroy
88
+ @discerner_search.deleted_at = Time.now
89
+ @discerner_search.save
90
+ respond_to do |format|
91
+ format.html { redirect_to searches_path }
92
+ end
93
+ end
94
+
95
+ def show
96
+ if @discerner_search.disabled?
97
+ error_message = "There is an issue with the this search that has to be corrected before it can be exported"
98
+ if @discerner_search.warnings.any?
99
+ error_message << ': '
100
+ error_message << @discerner_search.warnings.full_messages.join(',')
101
+ end
102
+ else
103
+ if dictionary_model
104
+ dictionary = dictionary_model.new(@discerner_search)
105
+ if not dictionary.respond_to?('export')
106
+ error_message = "Model '#{dictionary_model_name}' instance does not respond to 'export' method. You need to implement it to be able to run export on this dictionary"
107
+ end
108
+ else
109
+ error_message = "Model '#{dictionary_model_name}' could not be found. You need to create it to be able to run export on this dictionary"
110
+ end
111
+ end
112
+ flash[:error] = error_message unless error_message.blank?
113
+
114
+ respond_to do |format|
115
+ if error_message
116
+ format.html
117
+ format.csv { redirect_to export_parameters_path(@discerner_search) }
118
+ format.xls { redirect_to export_parameters_path(@discerner_search) }
119
+ else
120
+ @export_data = dictionary.export(params, dictionary_search_options)
121
+ filename ="#{@discerner_search.parameterized_name}_#{Date.today.strftime('%m_%d_%Y')}"
122
+ format.html
123
+ format.csv do
124
+
125
+ send_data @export_data,
126
+ :type => 'text/csv; charset=iso-8859-1; header=present',
127
+ :disposition => "attachment; filename=#{filename}.csv"
128
+ end
129
+ format.xls do
130
+ headers["Content-type"] = "application/vnd.ms-excel"
131
+ headers['Content-Transfer-Encoding'] = 'binary'
132
+ headers['Expires'] = '0'
133
+ headers['Pragma'] = 'public'
134
+ headers["Cache-Control"] = "must-revalidate, post-check=0, pre-check=0"
135
+ headers["Content-Disposition"] = "attachment; filename=\"#{filename}.xls\""
136
+ headers['Content-Description'] = 'File Transfer'
137
+ render "discerner/dictionaries/#{@discerner_search.dictionary.parameterized_name}/show"
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ private
144
+ def load_search
145
+ @discerner_search = Discerner::Search.find(params[:id])
146
+ end
147
+
148
+ def dictionary_model_name
149
+ @discerner_search.dictionary.parameterized_name.camelize
150
+ end
151
+
152
+ def dictionary_model
153
+ dictionary_model_name.safe_constantize
154
+ end
155
+
156
+ def dictionary_search_options
157
+ options = { :username => nil }
158
+ options[:username] = discerner_user.username unless discerner_user.blank?
159
+ options
160
+ end
161
+
162
+ def set_searchable_dictionaries
163
+ if @discenrer_search && @discerner_search.persisted?
164
+ @searchable_dictionaries = [@discerner_search.dictionary]
165
+ else
166
+ @searchable_dictionaries = Discerner::Dictionary.not_deleted
167
+ end
168
+ end
169
+
170
+ def set_searchables
171
+ if @discerner_search
172
+ dictionary_ids = []
173
+ dictionary_ids << @discerner_search.dictionary_id
174
+ else
175
+ dictionary_ids = @searchable_dictionaries.map(&:id)
176
+ end
177
+
178
+ @searchable_parameter_categories = Discerner::ParameterCategory.includes(:dictionary).where(:dictionary_id => dictionary_ids).not_deleted.searchable.ordered_by_name.to_a
179
+ parameters_available = Discerner::Parameter.includes(:parameter_type, :parameter_category => [:dictionary]).where(:parameter_category_id => @searchable_parameter_categories.map(&:id)).not_deleted.searchable.to_a
180
+ parameters_used = @discerner_search && @discerner_search.persisted? ? @discerner_search.search_parameters.map{ |sp| sp.parameter } : []
181
+ @searchable_parameters = parameters_available.flatten | parameters_used.flatten
182
+ @searchable_parameter_values = map_searchable_values
183
+ end
184
+
185
+ def map_searchable_values
186
+ searchable_values = {}
187
+
188
+ # getting all values at once to save database calls
189
+ values_available = Discerner::ParameterValue.includes(:parameter_value_category).not_deleted.where(:parameter_id => @searchable_parameters.map(&:id)).ordered_by_parameter_and_name.to_a
190
+ values_used = []
191
+ if @discerner_search && @discerner_search.persisted?
192
+ values_used = Discerner::ParameterValue.includes(:parameter_value_category).joins(:search_parameter_values => :search_parameter).where(:discerner_search_parameters => {:search_id => @discerner_search.id}).ordered_by_parameter_and_name.to_a
193
+ end
194
+
195
+ @searchable_parameters.each do |sp|
196
+ values = values_available.select{|pv| pv.parameter_id == sp.id} | values_used.select{|pv| pv.parameter_id == sp.id}
197
+ searchable_values[sp.id] = values.uniq.reject{|v| v.blank?}
198
+ end
199
+ searchable_values
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,145 @@
1
+ module Discerner
2
+ module Methods
3
+ module Helpers
4
+ module SearchesHelper
5
+ def discerner_results_partial
6
+ "discerner/dictionaries/#{@discerner_search.dictionary.parameterized_name}/results"
7
+ end
8
+
9
+ def generate_nested_attributes_template(f, association, association_prefix = nil )
10
+ if association_prefix.nil?
11
+ association_prefix = association.to_s.singularize
12
+ end
13
+ new_object = f.object.class.reflect_on_association(association).klass.new
14
+ fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |form_builder|
15
+ render(association_prefix + "_fields", :f => form_builder)
16
+ end
17
+ escape_javascript(fields)
18
+ end
19
+
20
+ def link_to_add_fields(name, association, html_options={})
21
+ css_class = html_options[:class] || ' '
22
+ css_class += "add_#{association.to_s} add add_link icon_link"
23
+ html_options[:class] = css_class
24
+ link_to(name, 'javascript:void(0);', html_options)
25
+ end
26
+
27
+ def link_to_remove_fields(name, f, association)
28
+ f.hidden_field(:_destroy) + link_to(name, "javascript:void(0);", :class => "delete_#{association.to_s} delete_link icon_link")
29
+ end
30
+
31
+ def link_to_soft_delete_fields(name, f, association)
32
+ f.hidden_field(:soft_delete) + link_to(name, "javascript:void(0);", :class => "delete_#{association.to_s} delete_link icon_link")
33
+ end
34
+
35
+ def nested_record_id(builder, assocation)
36
+ builder.object.id.nil? ? "new_nested_record" : "#{assocation.to_s.singularize}_#{builder.object.id}"
37
+ end
38
+
39
+ def operator_options(type=nil)
40
+ operators = Discerner::Operator.not_deleted
41
+ unless type.blank?
42
+ operators = operators.joins(:parameter_types).where("discerner_parameter_types.name in (?)", type).
43
+ select('DISTINCT text, discerner_operators.id, discerner_operators.operator_type')
44
+ end
45
+ operators.includes(:parameter_types).uniq.map {|o| [o.text, o.id, {:class => o.css_class_name}]}
46
+ end
47
+
48
+ def dictionary_options(searchable_dictionaries)
49
+ searchable_dictionaries.map{|d| [d.name, d.id, {:class => d.css_class_name}]}
50
+ end
51
+
52
+ def combined_searches_options(search=nil)
53
+ all_searches = Discerner::Search.order(:id)
54
+
55
+ username = discerner_user.username unless discerner_user.blank?
56
+ all_searches = all_searches.by_user(username) unless username.blank?
57
+
58
+ if search.blank? || !search.persisted?
59
+ searches = all_searches.not_deleted.reject{|s| s.disabled?}
60
+ else
61
+ searches_available = all_searches.not_deleted.
62
+ where('id != ? and dictionary_id = ?', search.id,search.dictionary_id).
63
+ reject{|s| s.nested_searches.include?(search) || s.disabled?}
64
+ searches_used = search.combined_searches
65
+ searches = searches_available | searches_used
66
+ end
67
+ searches.map {|s| [s.display_name, s.id, {:class => s.dictionary.css_class_name}]}
68
+ end
69
+
70
+ def parameter_options(searchable_parameters, base_id=nil)
71
+ options = []
72
+ searchable_parameters.each do |p|
73
+ option = [p.display_name, p.id]
74
+ html_options = {:class => p.css_class_name}
75
+ html_options[:id] = searchable_object_index(p, base_id) unless base_id.blank?
76
+ option << html_options
77
+ options << option
78
+ end
79
+ options
80
+ end
81
+
82
+ def parameter_value_options(searchable_values, base_id=nil)
83
+ options = []
84
+ searchable_values.each do |pv|
85
+ option = [pv.display_name, pv.id]
86
+ html_options = {}
87
+ html_options[:id] = searchable_object_index(pv, base_id) unless base_id.blank?
88
+ option << html_options
89
+ options << option
90
+ end
91
+ options
92
+ end
93
+
94
+ def searchable_object_index(object, base_id=nil)
95
+ "#{base_id}_#{object.id}"
96
+ end
97
+
98
+ def exportable_parameter_categories(search=nil)
99
+ if search.blank? || !search.persisted?
100
+ parameter_categories = Discerner::ParameterCategory.not_deleted.exportable.to_a
101
+ else
102
+ parameter_categories_available = search.dictionary.parameter_categories.exportable.to_a
103
+ parameter_categories_used = search.export_parameters.map{ |ep| ep.parameter.parameter_category }.flatten
104
+ parameter_categories = parameter_categories_available | parameter_categories_used
105
+ end
106
+ parameter_categories.sort{|a,b| a.parameters.length <=> b.parameters.length}
107
+ end
108
+
109
+ def exportable_parameters(search, category)
110
+ return if search.blank? || !search.persisted?
111
+ parameters_available = category.parameters.exportable.to_a
112
+ parameters_used = search.export_parameters.map{|ep| ep.parameter}.reject{|p| p.parameter_category != category }.flatten
113
+ parameters = parameters_available | parameters_used
114
+ parameters.sort{|a,b| a.name <=> b.name}
115
+ end
116
+
117
+ def search_parameter_values(search_parameter)
118
+ search_parameter_values = search_parameter.parameter.parameter_type.name == 'list' ? search_parameter.search_parameter_values.chosen : search_parameter.search_parameter_values
119
+ display_values = []
120
+ search_parameter_values.each do |spv|
121
+ string = ''
122
+ value = spv.parameter_value.blank? ? spv.value : spv.parameter_value.name
123
+ string += spv.operator.text unless spv.operator.blank?
124
+ string += " \"#{value}\"" unless value.blank?
125
+ string += " \"#{spv.additional_value}\"" unless spv.additional_value.blank?
126
+ display_values << string
127
+ end
128
+ display_values.join(' or ')
129
+ end
130
+
131
+ def discerner_export_link
132
+ link_to "Export options", export_parameters_path(@discerner_search), :class => "discerner-button discerner-button-positive"
133
+ end
134
+
135
+ def format_datetime(datetime)
136
+ datetime.strftime("%m/%d/%Y %I:%M %p") if datetime
137
+ end
138
+
139
+ def format_date(date)
140
+ date.strftime("%m/%d/%Y") if date
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,54 @@
1
+ module Discerner
2
+ module Methods
3
+ module Models
4
+ module Dictionary
5
+ def self.included(base)
6
+ base.send :include, SoftDelete
7
+
8
+ # Associations
9
+ base.send :has_many, :parameter_categories, :dependent => :destroy
10
+ base.send :has_many, :searches
11
+
12
+ #Validations
13
+ base.send :validates, :name, :presence => true, :uniqueness => {:message => "for dictionary has already been taken"}
14
+
15
+ # Hooks
16
+ base.send :after_commit, :cascade_delete_parameter_categories, :on => :update, :if => Proc.new { |record| record.previous_changes.include?('deleted_at') }
17
+
18
+ # Whitelisting attributes
19
+ base.send :attr_accessible, :name, :deleted_at
20
+ end
21
+
22
+ # Instance Methods
23
+ def initialize(*args)
24
+ super(*args)
25
+ end
26
+
27
+ def css_class_name
28
+ "dictionary_#{parameterized_name}"
29
+ end
30
+
31
+ def parameterized_name
32
+ name.parameterize.underscore
33
+ end
34
+
35
+ def searchable_categories
36
+ parameter_categories.searchable
37
+ end
38
+
39
+ def exportable_categories
40
+ parameter_categories.exportable
41
+ end
42
+
43
+ private
44
+ def cascade_delete_parameter_categories
45
+ return unless deleted?
46
+ parameter_categories.each do |pc|
47
+ pc.deleted_at = Time.now
48
+ pc.save
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end