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.
- 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
|