discerner 1.1.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +97 -0
- data/Rakefile +29 -0
- data/app/assets/images/discerner/add.png +0 -0
- data/app/assets/images/discerner/ajax-loader.gif +0 -0
- data/app/assets/images/discerner/bar.gif +0 -0
- data/app/assets/images/discerner/bullet_arrow_down.png +0 -0
- data/app/assets/images/discerner/bullet_arrow_up.png +0 -0
- data/app/assets/images/discerner/cog.png +0 -0
- data/app/assets/images/discerner/delete.png +0 -0
- data/app/assets/images/discerner/edit.png +0 -0
- data/app/assets/images/discerner/excel.png +0 -0
- data/app/assets/images/discerner/greencheck.gif +0 -0
- data/app/assets/images/discerner/rails.png +0 -0
- data/app/assets/images/discerner/show.png +0 -0
- data/app/assets/images/discerner/switch_minus.gif +0 -0
- data/app/assets/images/discerner/switch_plus.gif +0 -0
- data/app/assets/javascripts/discerner/application.js +20 -0
- data/app/assets/javascripts/discerner/combobox.js +301 -0
- data/app/assets/javascripts/discerner/discerner.js +19 -0
- data/app/assets/javascripts/discerner/export_parameters.js +13 -0
- data/app/assets/javascripts/discerner/jquery/jquery.blockUI.js +576 -0
- data/app/assets/javascripts/discerner/jquery/jquery.form.js +1074 -0
- data/app/assets/javascripts/discerner/nested_attributes.js +69 -0
- data/app/assets/javascripts/discerner/search_combinations.js +49 -0
- data/app/assets/javascripts/discerner/search_parameter.js +131 -0
- data/app/assets/javascripts/discerner/search_parameter_value.js +172 -0
- data/app/assets/javascripts/discerner/searches.js +93 -0
- data/app/assets/javascripts/discerner/url.js +42 -0
- data/app/assets/stylesheets/discerner/application.css +16 -0
- data/app/assets/stylesheets/discerner/buttons.sass +13 -0
- data/app/assets/stylesheets/discerner/categorized_autocompleter.sass +53 -0
- data/app/assets/stylesheets/discerner/discerner.sass +51 -0
- data/app/assets/stylesheets/discerner/export_parameters.sass +43 -0
- data/app/assets/stylesheets/discerner/links.sass +29 -0
- data/app/assets/stylesheets/discerner/searches.sass +205 -0
- data/app/assets/stylesheets/discerner/tables.sass +32 -0
- data/app/controllers/discerner/application_controller.rb +2 -0
- data/app/controllers/discerner/export_parameters_controller.rb +5 -0
- data/app/controllers/discerner/parameters_controller.rb +5 -0
- data/app/controllers/discerner/searches_controller.rb +5 -0
- data/app/helpers/discerner/application_helper.rb +4 -0
- data/app/helpers/discerner/parameters_helper.rb +5 -0
- data/app/helpers/discerner/searches_helper.rb +5 -0
- data/app/models/discerner/dictionary.rb +5 -0
- data/app/models/discerner/export_parameter.rb +5 -0
- data/app/models/discerner/operator.rb +5 -0
- data/app/models/discerner/parameter.rb +5 -0
- data/app/models/discerner/parameter_category.rb +5 -0
- data/app/models/discerner/parameter_type.rb +5 -0
- data/app/models/discerner/parameter_value.rb +5 -0
- data/app/models/discerner/parameter_value_categorization.rb +5 -0
- data/app/models/discerner/parameter_value_category.rb +5 -0
- data/app/models/discerner/search.rb +5 -0
- data/app/models/discerner/search_combination.rb +5 -0
- data/app/models/discerner/search_parameter.rb +5 -0
- data/app/models/discerner/search_parameter_value.rb +5 -0
- data/app/views/discerner/export_parameters/index.html.haml +55 -0
- data/app/views/discerner/parameters/_values_autocompleter.html.haml +49 -0
- data/app/views/discerner/parameters/values.html.haml +1 -0
- data/app/views/discerner/searches/_form.html.haml +21 -0
- data/app/views/discerner/searches/_form_combined_searches.html.haml +32 -0
- data/app/views/discerner/searches/_form_controls.html.haml +8 -0
- data/app/views/discerner/searches/_form_header.html.haml +39 -0
- data/app/views/discerner/searches/_form_search_parameters.html.haml +28 -0
- data/app/views/discerner/searches/_list.html.haml +17 -0
- data/app/views/discerner/searches/_search_combination_fields.html.haml +22 -0
- data/app/views/discerner/searches/_search_parameter_fields.html.haml +48 -0
- data/app/views/discerner/searches/_search_parameter_value_fields.html.haml +62 -0
- data/app/views/discerner/searches/_summary.html.haml +25 -0
- data/app/views/discerner/searches/edit.html.haml +8 -0
- data/app/views/discerner/searches/index.html.haml +13 -0
- data/app/views/discerner/searches/index.js.haml +1 -0
- data/app/views/discerner/searches/new.html.haml +3 -0
- data/app/views/discerner/searches/rename.html.haml +6 -0
- data/app/views/discerner/searches/update.js.haml +7 -0
- data/app/views/discerner/shared/_categorized_autocompleter_items.html.haml +15 -0
- data/app/views/discerner/shared/_error_messages.html.haml +5 -0
- data/app/views/layouts/discerner/searches.html.erb +17 -0
- data/config/cucumber.yml +8 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20121004040716_create_discerner_dictionaries.rb +11 -0
- data/db/migrate/20121004153043_create_discerner_parameter_categories.rb +12 -0
- data/db/migrate/20121005194843_create_discerner_parameter_types.rb +11 -0
- data/db/migrate/20121005203223_create_discerner_parameters.rb +14 -0
- data/db/migrate/20121008154855_create_discerner_operators.rb +13 -0
- data/db/migrate/20121008160313_create_discerner_operators_parameter_types.rb +8 -0
- data/db/migrate/20121008161455_create_discerner_parameter_values.rb +13 -0
- data/db/migrate/20121008180829_create_discerner_searches.rb +11 -0
- data/db/migrate/20121008182443_create_discerner_search_parameters.rb +11 -0
- data/db/migrate/20121011205130_create_discerner_search_parameter_values.rb +15 -0
- data/db/migrate/20121211213215_add_dictionary_id_to_discerner_searches.rb +5 -0
- data/db/migrate/20130205193602_create_discerner_search_combinations.rb +12 -0
- data/db/migrate/20130211230636_create_discerner_export_parameters.rb +9 -0
- data/db/migrate/20130213185818_add_search_columns_to_discerner_parameters.rb +38 -0
- data/db/migrate/20130213205255_rename_database_name_to_search_value_in_discerner_parameter_values.rb +5 -0
- data/db/migrate/20130215165416_add_searchable_to_discerner_parameters.rb +5 -0
- data/db/migrate/20130218230257_add_exclusive_to_discerner_parameters.rb +5 -0
- data/db/migrate/20130220163015_replace_integer_type_with_numeric.rb +22 -0
- data/db/migrate/20130221172826_add_unique_identifier_to_discerner_parameters.rb +5 -0
- data/db/migrate/20130222052924_change_search_attribute_to_method.rb +29 -0
- data/db/migrate/20130222070959_add_export_columns_to_discerner_parameters.rb +6 -0
- data/db/migrate/20130227031747_add_unique_identifier_to_discerner_operators.rb +16 -0
- data/db/migrate/20130306015019_change_discerner_parameter_values_name.rb +9 -0
- data/db/migrate/20130306212430_add_deleted_at_to_discerner_search_parameters.rb +5 -0
- data/db/migrate/20130306212504_add_deleted_at_to_discerner_search_parameter_values.rb +5 -0
- data/db/migrate/20130306212527_add_deleted_at_to_discerner_search_combinations.rb +5 -0
- data/db/migrate/20130306212818_add_deleted_at_to_discerner_export_parameters.rb +5 -0
- data/db/migrate/20130311190717_add_operator_type_to_discerner_operators.rb +5 -0
- data/db/migrate/20131212175110_remove_extra_search_parameter_values.rb +10 -0
- data/db/migrate/20140204170625_create_discerner_parameter_value_categories.rb +16 -0
- data/db/migrate/20140204170646_create_discerner_parameter_value_categorizations.rb +12 -0
- data/db/migrate/20140227191827_remove_blank_parameter_values_from_export_parameters.rb +10 -0
- data/db/seeds.rb +0 -0
- data/lib/discerner/engine.rb +16 -0
- data/lib/discerner/methods/controllers/export_parameters_controller.rb +38 -0
- data/lib/discerner/methods/controllers/parameters_controller.rb +30 -0
- data/lib/discerner/methods/controllers/searches_controller.rb +204 -0
- data/lib/discerner/methods/helpers/searches_helper.rb +145 -0
- data/lib/discerner/methods/models/dictionary.rb +54 -0
- data/lib/discerner/methods/models/export_parameter.rb +35 -0
- data/lib/discerner/methods/models/operator.rb +42 -0
- data/lib/discerner/methods/models/parameter.rb +90 -0
- data/lib/discerner/methods/models/parameter_category.rb +60 -0
- data/lib/discerner/methods/models/parameter_type.rb +33 -0
- data/lib/discerner/methods/models/parameter_value.rb +87 -0
- data/lib/discerner/methods/models/parameter_value_categorization.rb +21 -0
- data/lib/discerner/methods/models/parameter_value_category.rb +45 -0
- data/lib/discerner/methods/models/search.rb +147 -0
- data/lib/discerner/methods/models/search_combination.rb +50 -0
- data/lib/discerner/methods/models/search_parameter.rb +128 -0
- data/lib/discerner/methods/models/search_parameter_value.rb +130 -0
- data/lib/discerner/methods/models/soft_delete.rb +35 -0
- data/lib/discerner/methods/models/warning.rb +15 -0
- data/lib/discerner/parser.rb +497 -0
- data/lib/discerner/version.rb +3 -0
- data/lib/discerner.rb +4 -0
- data/lib/generators/discerner/dictionary/dictionary_generator.rb +38 -0
- data/lib/generators/discerner/dictionary/templates/model.rb +15 -0
- data/lib/generators/discerner/dictionary/templates/show.xls.erb +37 -0
- data/lib/generators/discerner/dictionary/templates/view.html.haml +2 -0
- data/lib/generators/discerner/install/install_generator.rb +153 -0
- data/lib/generators/discerner/install/templates/controllers/export_parameters_controller.rb +20 -0
- data/lib/generators/discerner/install/templates/controllers/parameters_controller.rb +15 -0
- data/lib/generators/discerner/install/templates/controllers/searches_controller.rb +39 -0
- data/lib/generators/discerner/install/templates/dictionaries.yml +236 -0
- data/lib/generators/discerner/install/templates/helpers/searches_helper.rb +9 -0
- data/lib/generators/discerner/install/templates/models/book.rb +15 -0
- data/lib/generators/discerner/install/templates/models/dictionary.rb +9 -0
- data/lib/generators/discerner/install/templates/models/export_parameter.rb +9 -0
- data/lib/generators/discerner/install/templates/models/operator.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter.rb +10 -0
- data/lib/generators/discerner/install/templates/models/parameter_category.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_type.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_value.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_value_categorization.rb +9 -0
- data/lib/generators/discerner/install/templates/models/parameter_value_category.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search_combination.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search_parameter.rb +9 -0
- data/lib/generators/discerner/install/templates/models/search_parameter_value.rb +9 -0
- data/lib/generators/discerner/install/templates/views/layouts/searches.html.erb +17 -0
- data/lib/setup/operators.yml +91 -0
- data/lib/tasks/cucumber.rake +65 -0
- data/lib/tasks/discerner_tasks.rake +30 -0
- 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,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,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
|
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
|