discerner 1.1.18

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