diff --git a/app/classes/query/base.rb b/app/classes/query/base.rb index 05ac15e772..672a9e8691 100644 --- a/app/classes/query/base.rb +++ b/app/classes/query/base.rb @@ -7,6 +7,7 @@ class Base include Query::Modules::BoundingBox include Query::Modules::Coercion include Query::Modules::Conditions + include Query::Modules::Associations include Query::Modules::Datetime include Query::Modules::GoogleSearch include Query::Modules::HighLevelQueries diff --git a/app/classes/query/field_slip_base.rb b/app/classes/query/field_slip_base.rb index 2dbf3929fa..ae0162d4bd 100644 --- a/app/classes/query/field_slip_base.rb +++ b/app/classes/query/field_slip_base.rb @@ -22,15 +22,6 @@ def initialize_flavor super end - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "field_slips.project_id = '#{project.id}'" - end - def self.default_order "date" end diff --git a/app/classes/query/image_base.rb b/app/classes/query/image_base.rb index 0bb480e010..8839732d64 100644 --- a/app/classes/query/image_base.rb +++ b/app/classes/query/image_base.rb @@ -53,8 +53,6 @@ def initialize_flavor add_join(:observation_images) if params[:with_observation] initialize_notes_parameters end - # add_by_user_condition("images") - # add_ids_condition add_pattern_condition add_advanced_search_conditions initialize_association_parameters @@ -86,22 +84,12 @@ def initialize_association_parameters end def add_project_conditions - add_for_project_condition + add_for_project_condition(:project_images) add_id_condition("project_images.project_id", lookup_projects_by_name(params[:projects]), :project_images) end - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "project_images.project_id = '#{project.id}'" - add_join(:project_images) - end - def initialize_image_parameters add_search_condition("images.copyright_holder", params[:copyright_holder_has]) diff --git a/app/classes/query/image_with_observations.rb b/app/classes/query/image_with_observations.rb index dc42f2db22..c110f5b537 100644 --- a/app/classes/query/image_with_observations.rb +++ b/app/classes/query/image_with_observations.rb @@ -28,50 +28,22 @@ def initialize_flavor initialize_association_parameters add_where_conditions initialize_boolean_parameters - initialize_search_parameters + initialize_obs_search_parameters add_bounding_box_conditions_for_observations initialize_content_filters(Observation) super end def initialize_association_parameters - add_id_condition( - "herbarium_records.herbarium_id", - lookup_herbaria_by_name(params[:herbaria]), - :observations, :observation_herbarium_records, :herbarium_records - ) - add_id_condition( - "project_observations.project_id", - lookup_projects_by_name(params[:projects]), - :observation_images, :observations, :project_observations - ) - add_for_project_condition + initialize_herbaria_parameter + initialize_projects_parameter(:project_observations) + add_for_project_condition(:project_observations, + [:observations, :project_observations]) add_in_species_list_condition end - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "project_observations.project_id = '#{params[:project]}'" - add_join(:observations, :project_observations) - end - - def add_in_species_list_condition - return if params[:species_list].blank? - - spl = find_cached_parameter_instance(SpeciesList, :species_list) - @title_tag = :query_title_in_species_list - @title_args[:species_list] = spl.format_name - add_join(:observation_images, :observations) - add_join(:observations, :species_list_observations) - where << "species_list_observations.species_list_id = '#{spl.id}'" - end - def add_where_conditions - add_at_location_parameter(:observations) + add_at_location_condition(:observations) add_search_condition("observations.where", params[:user_where]) end @@ -79,67 +51,16 @@ def initialize_boolean_parameters initialize_is_collection_location_parameter initialize_with_public_lat_lng_parameter initialize_with_name_parameter - initialize_with_notes_parameter + initialize_with_obs_notes_parameter add_join(:observations, :comments) if params[:with_comments] add_join(:observations, :sequences) if params[:with_sequences] add_with_notes_fields_condition(params[:with_notes_fields]) end - def initialize_is_collection_location_parameter - add_boolean_condition( - "observations.is_collection_location IS TRUE", - "observations.is_collection_location IS FALSE", - params[:is_collection_location] - ) - end - - def initialize_with_public_lat_lng_parameter - add_boolean_condition( - "observations.lat IS NOT NULL AND observations.gps_hidden IS FALSE", - "observations.lat IS NULL OR observations.gps_hidden IS TRUE", - params[:with_public_lat_lng] - ) - end - - def initialize_with_name_parameter - genus = Name.ranks[:Genus] - group = Name.ranks[:Group] - add_boolean_condition( - "names.`rank` <= #{genus} or names.`rank` = #{group}", - "names.`rank` > #{genus} and names.`rank` < #{group}", - params[:with_name], - :observations, :names - ) - end - - def initialize_with_notes_parameter - add_boolean_condition( - "observations.notes != #{escape(Observation.no_notes_persisted)}", - "observations.notes = #{escape(Observation.no_notes_persisted)}", - params[:with_notes] - ) - end - - def initialize_search_parameters - add_search_condition( - "observations.notes", - params[:notes_has] - ) - add_search_condition( - "CONCAT(comments.summary,COALESCE(comments.comment,''))", - params[:comments_has], - :observations, :comments - ) - end - def default_order "name" end - def coerce_into_observation_query - Query.lookup(:Observation, :all, params_back_to_observation_params) - end - def title default = super with_observations_query_description || default diff --git a/app/classes/query/initializers/descriptions.rb b/app/classes/query/initializers/descriptions.rb index 8a8ed65245..7db4134632 100644 --- a/app/classes/query/initializers/descriptions.rb +++ b/app/classes/query/initializers/descriptions.rb @@ -25,20 +25,54 @@ def descriptions_coercion_parameter_declarations } end - def params_out_to_with_descriptions_params - pargs = params_plus_old_by - return pargs if pargs[:ids].blank? + def add_desc_ids_condition(type) + return unless params[:desc_ids] - pargs[:desc_ids] = pargs.delete(:ids) - pargs + set = clean_id_set(params[:desc_ids]) + @where << "#{type}_descriptions.id IN (#{set})" + self.order = "FIND_IN_SET(#{type}_descriptions.id,'#{set}') ASC" + + @title_tag = :query_title_with_descriptions.t(type: type) + @title_args[:descriptions] = params[:old_title] || + :query_title_in_set.t(type: :description) end - def params_back_to_description_params - pargs = params_with_old_by_restored - return pargs if pargs[:desc_ids].blank? + def add_desc_by_user_condition(type) + return unless params[:by_user] - pargs[:ids] = pargs.delete(:desc_ids) - pargs + user = find_cached_parameter_instance(User, :by_user) + @title_tag = :query_title_with_descriptions_by_user.t(type: type) + @title_args[:user] = user.legal_name + add_join(:"#{type}_descriptions") + where << "#{type}_descriptions.user_id = '#{user.id}'" + end + + def add_desc_by_author_condition(type) + return unless params[:by_author] + + # Change this conditional to check for :with_descriptions param + with_desc = [Name, Location].include?(model) ? "_with_descriptions" : "" + user = find_cached_parameter_instance(User, :by_author) + @title_tag = :"query_title#{with_desc}_by_author".t( + type: :"#{type}_description", user: user.legal_name + ) + @title_args[:user] = user.legal_name + add_join(:"#{type}_descriptions", :"#{type}_description_authors") + where << "#{type}_description_authors.user_id = '#{user.id}'" + end + + def add_desc_by_editor_condition(type) + return unless params[:by_editor] + + # Change this conditional to check for :with_descriptions param + with_desc = [Name, Location].include?(model) ? "_with_descriptions" : "" + user = find_cached_parameter_instance(User, :by_editor) + @title_tag = :"query_title#{with_desc}_by_editor".t( + type: :"#{type}_description", user: user.legal_name + ) + @title_args[:user] = user.legal_name + add_join(:"#{type}_descriptions", :"#{type}_description_editors") + where << "#{type}_description_editors.user_id = '#{user.id}'" end def initialize_description_parameters(type = :name) @@ -95,6 +129,22 @@ def initialize_desc_content_parameter(type) fields = "CONCAT(#{fields.join(",")})" add_search_condition(fields, params[:desc_content]) end + + def params_out_to_with_descriptions_params + pargs = params_plus_old_by + return pargs if pargs[:ids].blank? + + pargs[:desc_ids] = pargs.delete(:ids) + pargs + end + + def params_back_to_description_params + pargs = params_with_old_by_restored + return pargs if pargs[:desc_ids].blank? + + pargs[:ids] = pargs.delete(:desc_ids) + pargs + end end end end diff --git a/app/classes/query/initializers/observations.rb b/app/classes/query/initializers/observations.rb index 974051c4b0..ed39ab367d 100644 --- a/app/classes/query/initializers/observations.rb +++ b/app/classes/query/initializers/observations.rb @@ -40,6 +40,117 @@ def observations_coercion_parameter_declarations } end + # This is just to allow the additional location conditions + def add_ids_condition(table = model.table_name, ids = :ids) + return if params[ids].nil? # [] is valid + + super + add_is_collection_location_condition_for_locations + end + + def initialize_obs_date_parameter(param_name = :date) + add_date_condition( + "observations.when", + params[param_name], + :observations + ) + end + + def initialize_confidence_parameter + add_range_condition( + "observations.vote_cache", + params[:confidence], + :observations + ) + end + + def initialize_project_lists_parameter + add_id_condition( + "species_list_observations.species_list_id", + lookup_lists_for_projects_by_name(params[:project_lists]), + :observations, :species_list_observations + ) + end + + def initialize_field_slips_parameter + return unless params[:field_slips] + + add_join(:field_slips) + add_exact_match_condition( + "field_slips.code", + params[:field_slips], + :observations + ) + end + + def initialize_is_collection_location_parameter + add_boolean_condition( + "observations.is_collection_location IS TRUE", + "observations.is_collection_location IS FALSE", + params[:is_collection_location], + :observations + ) + end + + def initialize_with_public_lat_lng_parameter + add_boolean_condition( + "observations.lat IS NOT NULL AND observations.gps_hidden IS FALSE", + "observations.lat IS NULL OR observations.gps_hidden IS TRUE", + params[:with_public_lat_lng], + :observations + ) + end + + def initialize_with_images_parameter + add_boolean_condition( + "observations.thumb_image_id IS NOT NULL", + "observations.thumb_image_id IS NULL", + params[:with_images], + :observations + ) + end + + def initialize_with_specimen_parameter + add_boolean_condition( + "observations.specimen IS TRUE", + "observations.specimen IS FALSE", + params[:with_specimen], + :observations + ) + end + + def initialize_with_name_parameter + genus = Name.ranks[:Genus] + group = Name.ranks[:Group] + add_boolean_condition( + "names.`rank` <= #{genus} or names.`rank` = #{group}", + "names.`rank` > #{genus} and names.`rank` < #{group}", + params[:with_name], + :observations, :names + ) + end + + def initialize_with_obs_notes_parameter(param_name = :with_notes) + add_boolean_condition( + "observations.notes != #{escape(Observation.no_notes_persisted)}", + "observations.notes = #{escape(Observation.no_notes_persisted)}", + params[param_name], + :observations + ) + end + + def initialize_obs_search_parameters + add_search_condition( + "observations.notes", + params[:notes_has] + ) + add_search_condition( + "CONCAT(comments.summary,COALESCE(comments.comment,''))", + params[:comments_has], + :observations, :comments + ) + end + def params_out_to_with_observations_params(pargs) return pargs if pargs[:ids].blank? @@ -54,6 +165,10 @@ def params_back_to_observation_params pargs[:ids] = pargs.delete(:obs_ids) pargs end + + def coerce_into_observation_query + Query.lookup(:Observation, :all, params_back_to_observation_params) + end end end end diff --git a/app/classes/query/location_description_base.rb b/app/classes/query/location_description_base.rb index 44bc450e55..1dd8e98297 100644 --- a/app/classes/query/location_description_base.rb +++ b/app/classes/query/location_description_base.rb @@ -26,8 +26,8 @@ def initialize_flavor add_ids_condition("location_descriptions") add_owner_and_time_stamp_conditions("location_descriptions") add_by_user_condition("location_descriptions") - add_by_author_condition - add_by_editor_condition + add_desc_by_author_condition(:location) + add_desc_by_editor_condition(:location) locations = lookup_locations_by_name(params[:locations]) add_id_condition("location_descriptions.location_id", locations) add_boolean_condition( @@ -38,28 +38,6 @@ def initialize_flavor super end - def add_by_author_condition - return unless params[:by_author] - - user = find_cached_parameter_instance(User, :by_author) - @title_tag = :query_title_by_author.t(type: :location_description, - user: user.legal_name) - @title_args[:user] = user.legal_name - add_join(:location_description_authors) - where << "location_description_authors.user_id = '#{user.id}'" - end - - def add_by_editor_condition - return unless params[:by_editor] - - user = find_cached_parameter_instance(User, :by_editor) - @title_tag = :query_title_by_editor.t(type: :location_description, - user: user.legal_name) - @title_args[:user] = user.legal_name - add_join(:location_description_editors) - where << "location_description_editors.user_id = '#{user.id}'" - end - def self.default_order "name" end diff --git a/app/classes/query/location_with_descriptions.rb b/app/classes/query/location_with_descriptions.rb index a6970c7328..39027335b2 100644 --- a/app/classes/query/location_with_descriptions.rb +++ b/app/classes/query/location_with_descriptions.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Query::LocationWithDescriptions < Query::LocationBase + include Query::Initializers::Descriptions + def parameter_declarations super.merge( desc_ids?: [LocationDescription] @@ -9,55 +11,13 @@ def parameter_declarations def initialize_flavor add_join(:location_descriptions) - add_ids_condition - add_by_user_condition - add_by_author_condition - add_by_editor_condition + add_desc_ids_condition(:location) + add_desc_by_user_condition(:location) + add_desc_by_author_condition(:location) + add_desc_by_editor_condition(:location) super end - def add_ids_condition - return unless params[:desc_ids] - - set = clean_id_set(params[:desc_ids]) - @where << "location_descriptions.id IN (#{set})" - self.order = "FIND_IN_SET(location_descriptions.id,'#{set}') ASC" - - @title_tag = :query_title_with_descriptions.t(type: :location) - @title_args[:descriptions] = params[:old_title] || - :query_title_in_set.t(type: :description) - end - - def add_by_user_condition - return unless params[:by_user] - - user = find_cached_parameter_instance(User, :by_user) - @title_tag = :query_title_with_descriptions_by_user.t(type: :location) - @title_args[:user] = user.legal_name - add_join(:location_descriptions) - where << "location_descriptions.user_id = '#{user.id}'" - end - - def add_by_author_condition - return unless params[:by_author] - - user = find_cached_parameter_instance(User, :by_author) - @title_tag = :query_title_with_descriptions_by_author.t(type: :location) - @title_args[:user] = user.legal_name - add_join(:location_descriptions, :location_description_authors) - where << "location_description_authors.user_id = '#{user.id}'" - end - - def add_by_editor_condition - return unless params[:by_editor] - - user = find_cached_parameter_instance(User, :by_editor) - @title_tag = :query_title_with_descriptions_by_editor.t(type: :location) - @title_args[:user] = user.legal_name - add_join(:location_descriptions, :location_description_editors) - where << "location_description_editors.user_id = '#{user.id}'" - end - def coerce_into_location_description_query Query.lookup(:LocationDescription, :all, params_back_to_description_params) end diff --git a/app/classes/query/location_with_observations.rb b/app/classes/query/location_with_observations.rb index cab7122f39..1140f3abb4 100644 --- a/app/classes/query/location_with_observations.rb +++ b/app/classes/query/location_with_observations.rb @@ -20,7 +20,7 @@ def parameter_declarations def initialize_flavor add_join(:observations) - add_ids_condition + add_ids_condition("observations", :obs_ids) add_owner_and_time_stamp_conditions("observations") add_by_user_condition("observations") add_date_condition("observations.when", params[:date]) @@ -29,132 +29,36 @@ def initialize_flavor initialize_association_parameters add_range_condition("observations.vote_cache", params[:confidence]) initialize_boolean_parameters - initialize_search_parameters + initialize_obs_search_parameters initialize_content_filters(Observation) super end - def add_ids_condition - return unless params[:obs_ids] - - set = clean_id_set(params[:obs_ids]) - @where << "observations.id IN (#{set})" - self.order = "FIND_IN_SET(observations.id,'#{set}') ASC" - - @title_args[:observations] = params[:old_title] || - :query_title_in_set.t(type: :observation) - where << "observations.is_collection_location IS TRUE" - end - def add_where_conditions add_where_condition(:observations, params[:locations]) - add_at_location_parameter(:observations) + add_at_location_condition(:observations) add_search_condition("observations.where", params[:user_where]) end def initialize_association_parameters - add_id_condition( - "project_observations.project_id", - lookup_projects_by_name(params[:projects]), - :observations, :project_observations - ) - add_for_project_condition - add_id_condition( - "species_list_observations.species_list_id", - lookup_species_lists_by_name(params[:species_lists]), - :observations, :species_list_observations - ) + project_joins = [:observations, :project_observations] + initialize_projects_parameter(:project_observations, project_joins) + add_for_project_condition(:project_observations, project_joins) + initialize_species_lists_parameter add_in_species_list_condition - add_id_condition( - "herbarium_records.herbarium_id", - lookup_herbaria_by_name(params[:herbaria]), - :observations, :observation_herbarium_records, :herbarium_records - ) - end - - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "project_observations.project_id = '#{params[:project]}'" - where << "observations.is_collection_location IS TRUE" - add_join(:observations, :project_observations) - end - - def add_in_species_list_condition - return if params[:species_list].blank? - - spl = find_cached_parameter_instance(SpeciesList, :species_list) - @title_tag = :query_title_in_species_list - @title_args[:species_list] = spl.format_name - add_join(:observations, :species_list_observations) - where << "species_list_observations.species_list_id = '#{spl.id}'" - where << "observations.is_collection_location IS TRUE" + initialize_herbaria_parameter end def initialize_boolean_parameters initialize_is_collection_location_parameter initialize_with_public_lat_lng_parameter initialize_with_name_parameter - initialize_with_notes_parameter + initialize_with_obs_notes_parameter add_with_notes_fields_condition(params[:with_notes_fields]) add_join(:observations, :comments) if params[:with_comments] add_join(:observations, :sequences) if params[:with_sequences] end - def initialize_is_collection_location_parameter - add_boolean_condition( - "observations.is_collection_location IS TRUE", - "observations.is_collection_location IS FALSE", - params[:is_collection_location] - ) - end - - def initialize_with_public_lat_lng_parameter - add_boolean_condition( - "observations.lat IS NOT NULL AND observations.gps_hidden IS FALSE", - "observations.lat IS NULL OR observations.gps_hidden IS TRUE", - params[:with_public_lat_lng] - ) - end - - def initialize_with_name_parameter - genus = Name.ranks[:Genus] - group = Name.ranks[:Group] - add_boolean_condition( - "names.`rank` <= #{genus} or names.`rank` = #{group}", - "names.`rank` > #{genus} and names.`rank` < #{group}", - params[:with_name], - :observations, :names - ) - end - - def initialize_with_notes_parameter - add_boolean_condition( - "observations.notes != #{escape(Observation.no_notes_persisted)}", - "observations.notes = #{escape(Observation.no_notes_persisted)}", - params[:with_notes] - ) - end - - def initialize_search_parameters - add_search_condition( - "observations.notes", - params[:notes_has] - ) - add_search_condition( - "CONCAT(comments.summary,COALESCE(comments.comment,''))", - params[:comments_has], - :observations, :comments - ) - end - - def coerce_into_observation_query - Query.lookup(:Observation, :all, params_back_to_observation_params) - end - def title default = super with_observations_query_description || default diff --git a/app/classes/query/modules/associations.rb b/app/classes/query/modules/associations.rb new file mode 100644 index 0000000000..5646070cc4 --- /dev/null +++ b/app/classes/query/modules/associations.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +module Query + module Modules + # Helper methods for turning Query parameters into SQL conditions. + module Associations + def initialize_herbaria_parameter + add_id_condition( + "herbarium_records.herbarium_id", + lookup_herbaria_by_name(params[:herbaria]), + :observations, :observation_herbarium_records, :herbarium_records + ) + end + + def initialize_herbarium_records_parameter + add_id_condition( + "observation_herbarium_records.herbarium_record_id", + lookup_herbarium_records_by_name(params[:herbarium_records]), + :observations, :observation_herbarium_records + ) + end + + def add_where_condition(table, vals, *) + return if vals.empty? + + loc_col = "#{table}.location_id" + where_col = "#{table}.where" + ids = clean_id_set(lookup_locations_by_name(vals)) + cond = "#{loc_col} IN (#{ids})" + vals.each do |val| + if /\D/.match?(val) + pattern = clean_pattern(val) + cond += " OR #{where_col} LIKE '%#{pattern}%'" + end + end + @where << cond + add_joins(*) + end + + def add_at_location_condition(table = model.table_name) + return unless params[:location] + + location = find_cached_parameter_instance(Location, :location) + title_args[:location] = location.title_display_name + @where << "#{table}.location_id = '#{location.id}'" + end + + def add_is_collection_location_condition_for_locations + return unless model == Location + + where << "observations.is_collection_location IS TRUE" + end + + def add_for_project_condition(table = model.table_name, joins = [table]) + return if params[:project].blank? + + project = find_cached_parameter_instance(Project, :project) + @title_tag = :query_title_for_project + @title_args[:project] = project.title + where << "#{table}.project_id = '#{params[:project]}'" + add_is_collection_location_condition_for_locations + add_join(*joins) + end + + def initialize_projects_parameter(table = :project_observations, + joins = [:observations, table]) + add_id_condition( + "#{table}.project_id", + lookup_projects_by_name(params[:projects]), + *joins + ) + end + + def add_in_species_list_condition(table = :species_list_observations, + joins = [:observations, table]) + return if params[:species_list].blank? + + spl = find_cached_parameter_instance(SpeciesList, :species_list) + @title_tag = :query_title_in_species_list + @title_args[:species_list] = spl.format_name + where << "#{table}.species_list_id = '#{spl.id}'" + add_is_collection_location_condition_for_locations + add_join(*joins) + end + + def initialize_species_lists_parameter( + table = :species_list_observations, joins = [:observations, table] + ) + add_id_condition( + "#{table}.species_list_id", + lookup_species_lists_by_name(params[:species_lists]), + *joins + ) + end + end + end +end diff --git a/app/classes/query/modules/conditions.rb b/app/classes/query/modules/conditions.rb index 868b9cee18..e8325c9fc1 100644 --- a/app/classes/query/modules/conditions.rb +++ b/app/classes/query/modules/conditions.rb @@ -129,31 +129,6 @@ def add_not_id_condition(col, ids, *) add_joins(*) end - def add_where_condition(table, vals, *) - return if vals.empty? - - loc_col = "#{table}.location_id" - where_col = "#{table}.where" - ids = clean_id_set(lookup_locations_by_name(vals)) - cond = "#{loc_col} IN (#{ids})" - vals.each do |val| - if /\D/.match?(val) - pattern = clean_pattern(val) - cond += " OR #{where_col} LIKE '%#{pattern}%'" - end - end - @where << cond - add_joins(*) - end - - def add_at_location_parameter(table) - return unless params[:location] - - location = find_cached_parameter_instance(Location, :location) - title_args[:location] = location.title_display_name - @where << "#{table}.location_id = '#{location.id}'" - end - def add_rank_condition(vals, *) return if vals.empty? diff --git a/app/classes/query/name_description_base.rb b/app/classes/query/name_description_base.rb index f030e54886..47498ac3eb 100644 --- a/app/classes/query/name_description_base.rb +++ b/app/classes/query/name_description_base.rb @@ -26,8 +26,8 @@ def initialize_flavor add_ids_condition("name_descriptions") add_owner_and_time_stamp_conditions("name_descriptions") add_by_user_condition("name_descriptions") - add_by_author_condition - add_by_editor_condition + add_desc_by_author_condition(:name) + add_desc_by_editor_condition(:name) names = lookup_names_by_name(names: params[:names]) add_id_condition("name_descriptions.name_id", names) add_boolean_condition( @@ -38,28 +38,6 @@ def initialize_flavor super end - def add_by_author_condition - return unless params[:by_author] - - user = find_cached_parameter_instance(User, :by_author) - @title_tag = :query_title_by_author.t(type: :name_description, - user: user.legal_name) - @title_args[:user] = user.legal_name - add_join(:name_description_authors) - where << "name_description_authors.user_id = '#{user.id}'" - end - - def add_by_editor_condition - return unless params[:by_editor] - - user = find_cached_parameter_instance(User, :by_editor) - @title_tag = :query_title_by_editor.t(type: :name_description, - user: user.legal_name) - @title_args[:user] = user.legal_name - add_join(:name_description_editors) - where << "name_description_editors.user_id = '#{user.id}'" - end - def self.default_order "name" end diff --git a/app/classes/query/name_with_descriptions.rb b/app/classes/query/name_with_descriptions.rb index fbf79a453f..0891a68bbd 100644 --- a/app/classes/query/name_with_descriptions.rb +++ b/app/classes/query/name_with_descriptions.rb @@ -9,55 +9,13 @@ def parameter_declarations def initialize_flavor add_join(:name_descriptions) - add_ids_condition - add_by_user_condition - add_by_author_condition - add_by_editor_condition + add_desc_ids_condition(:name) + add_desc_by_user_condition(:name) + add_desc_by_author_condition(:name) + add_desc_by_editor_condition(:name) super end - def add_ids_condition - return unless params[:desc_ids] - - set = clean_id_set(params[:desc_ids]) - @where << "name_descriptions.id IN (#{set})" - self.order = "FIND_IN_SET(name_descriptions.id,'#{set}') ASC" - - @title_tag = :query_title_with_descriptions.t(type: :name) - @title_args[:descriptions] = params[:old_title] || - :query_title_in_set.t(type: :description) - end - - def add_by_user_condition - return unless params[:by_user] - - user = find_cached_parameter_instance(User, :by_user) - @title_tag = :query_title_with_descriptions_by_user.t(type: :name) - @title_args[:user] = user.legal_name - add_join(:name_descriptions) - where << "name_descriptions.user_id = '#{user.id}'" - end - - def add_by_author_condition - return unless params[:by_author] - - user = find_cached_parameter_instance(User, :by_author) - @title_tag = :query_title_with_descriptions_by_author.t(type: :name) - @title_args[:user] = user.legal_name - add_join(:name_descriptions, :name_description_authors) - where << "name_description_authors.user_id = '#{user.id}'" - end - - def add_by_editor_condition - return unless params[:by_editor] - - user = find_cached_parameter_instance(User, :by_editor) - @title_tag = :query_title_with_descriptions_by_editor.t(type: :name) - @title_args[:user] = user.legal_name - add_join(:name_descriptions, :name_description_editors) - where << "name_description_editors.user_id = '#{user.id}'" - end - def coerce_into_name_description_query Query.lookup(:NameDescription, :all, params_back_to_description_params) end diff --git a/app/classes/query/name_with_observations.rb b/app/classes/query/name_with_observations.rb index b9084e3c3e..3e5495ca3d 100644 --- a/app/classes/query/name_with_observations.rb +++ b/app/classes/query/name_with_observations.rb @@ -28,7 +28,7 @@ def initialize_flavor add_where_conditions initialize_association_parameters initialize_boolean_parameters - initialize_search_parameters + initialize_obs_search_parameters initialize_name_parameters(:observations) add_range_condition("observations.vote_cache", params[:confidence]) add_bounding_box_conditions_for_observations @@ -37,42 +37,15 @@ def initialize_flavor end def initialize_association_parameters - add_id_condition( - "project_observations.project_id", - lookup_projects_by_name(params[:projects]), - :observations, :project_observations - ) - add_for_project_condition + project_joins = [:observations, :project_observations] + initialize_projects_parameter(:project_observations, project_joins) + add_for_project_condition(:project_observations, project_joins) add_in_species_list_condition - add_id_condition( - "herbarium_records.herbarium_id", - lookup_herbaria_by_name(params[:herbaria]), - :observations, :observation_herbarium_records, :herbarium_records - ) - end - - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "project_observations.project_id = '#{params[:project]}'" - add_join(:observations, :project_observations) - end - - def add_in_species_list_condition - return if params[:species_list].blank? - - spl = find_cached_parameter_instance(SpeciesList, :species_list) - @title_tag = :query_title_in_species_list - @title_args[:species_list] = spl.format_name - where << "species_list_observations.species_list_id = '#{spl.id}'" - add_join(:observations, :species_list_observations) + initialize_herbaria_parameter end def add_where_conditions - add_at_location_parameter(:observations) + add_at_location_condition(:observations) add_search_condition("observations.where", params[:user_where]) end @@ -80,62 +53,12 @@ def initialize_boolean_parameters initialize_is_collection_location_parameter initialize_with_public_lat_lng_parameter initialize_with_name_parameter - initialize_with_notes_parameter + initialize_with_obs_notes_parameter add_with_notes_fields_condition(params[:with_notes_fields]) add_join(:observations, :comments) if params[:with_comments] add_join(:observations, :sequences) if params[:with_sequences] end - def initialize_is_collection_location_parameter - add_boolean_condition( - "observations.is_collection_location IS TRUE", - "observations.is_collection_location IS FALSE", - params[:is_collection_location] - ) - end - - def initialize_with_public_lat_lng_parameter - add_boolean_condition( - "observations.lat IS NOT NULL AND observations.gps_hidden IS FALSE", - "observations.lat IS NULL OR observations.gps_hidden IS TRUE", - params[:with_public_lat_lng] - ) - end - - def initialize_with_name_parameter - genus = Name.ranks[:Genus] - group = Name.ranks[:Group] - add_boolean_condition( - "names.`rank` <= #{genus} or names.`rank` = #{group}", - "names.`rank` > #{genus} and names.`rank` < #{group}", - params[:with_name] - ) - end - - def initialize_with_notes_parameter - add_boolean_condition( - "observations.notes != #{escape(Observation.no_notes_persisted)}", - "observations.notes = #{escape(Observation.no_notes_persisted)}", - params[:with_notes] - ) - end - - def initialize_search_parameters - add_search_condition( - "observations.notes", - params[:notes_has] - ) - add_search_condition( - "CONCAT(comments.summary,COALESCE(comments.comment,''))", - params[:comments_has], - :observations, :comments - ) - end - - def coerce_into_observation_query - Query.lookup(:Observation, :all, params_back_to_observation_params) - end - def title default = super with_observations_query_description || default diff --git a/app/classes/query/observation_base.rb b/app/classes/query/observation_base.rb index dabb651c0f..96eb7343b6 100644 --- a/app/classes/query/observation_base.rb +++ b/app/classes/query/observation_base.rb @@ -45,25 +45,23 @@ def local_parameter_declarations } end - # rubocop:disable Metrics/AbcSize def initialize_flavor add_ids_condition add_owner_and_time_stamp_conditions("observations") add_by_user_condition("observations") - add_date_condition("observations.when", params[:date]) + initialize_obs_date_parameter(:date) add_pattern_condition add_advanced_search_conditions add_needs_naming_condition initialize_name_parameters initialize_association_parameters initialize_boolean_parameters - initialize_search_parameters - add_range_condition("observations.vote_cache", params[:confidence]) + initialize_obs_search_parameters + initialize_confidence_parameter add_bounding_box_conditions_for_observations initialize_content_filters(Observation) super end - # rubocop:enable Metrics/AbcSize def add_pattern_condition return if params[:pattern].blank? @@ -80,87 +78,17 @@ def add_advanced_search_conditions def initialize_association_parameters add_where_condition("observations", params[:locations]) - add_at_location_parameter(:observations) + add_at_location_condition initialize_herbaria_parameter initialize_herbarium_records_parameter - add_for_project_condition - initialize_projects_parameter + add_for_project_condition(:project_observations) + initialize_projects_parameter(:project_observations) initialize_project_lists_parameter add_in_species_list_condition initialize_species_lists_parameter initialize_field_slips_parameter end - def initialize_herbaria_parameter - add_id_condition( - "herbarium_records.herbarium_id", - lookup_herbaria_by_name(params[:herbaria]), - :observation_herbarium_records, :herbarium_records - ) - end - - def initialize_herbarium_records_parameter - add_id_condition( - "observation_herbarium_records.herbarium_record_id", - lookup_herbarium_records_by_name(params[:herbarium_records]), - :observation_herbarium_records - ) - end - - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "project_observations.project_id = '#{params[:project]}'" - add_join("project_observations") - end - - def initialize_projects_parameter - add_id_condition( - "project_observations.project_id", - lookup_projects_by_name(params[:projects]), - :project_observations - ) - end - - def initialize_project_lists_parameter - add_id_condition( - "species_list_observations.species_list_id", - lookup_lists_for_projects_by_name(params[:project_lists]), - :species_list_observations - ) - end - - def add_in_species_list_condition - return if params[:species_list].blank? - - spl = find_cached_parameter_instance(SpeciesList, :species_list) - @title_tag = :query_title_in_species_list - @title_args[:species_list] = spl.format_name - where << "species_list_observations.species_list_id = '#{spl.id}'" - add_join(:species_list_observations) - end - - def initialize_species_lists_parameter - add_id_condition( - "species_list_observations.species_list_id", - lookup_species_lists_by_name(params[:species_lists]), - :species_list_observations - ) - end - - def initialize_field_slips_parameter - return unless params[:field_slips] - - add_join(:field_slips) - add_exact_match_condition( - "field_slips.code", - params[:field_slips] - ) - end - def add_needs_naming_condition return unless params[:needs_naming] @@ -220,76 +148,16 @@ def add_location_in_region_condition where << conds end - # The tricky thing here is, without the user.id being the value passed in - # params[:filter][:term], we're hunting for a user from a string like - # "Name ". Better to have the id as the value! - # Below uses the method in query/initializers/advanced_search to get a - # string but is expensive. Something like - # joins(:users).where((User[:login] + User[:name]).matches(str)) - # def add_by_user_condition - # return unless params[:by_user] - # - # user = find_cached_parameter_instance(User, :by_user) - # user = params[:by_user].to_s.gsub(/ *<[^<>]*>/, "") - # end - def initialize_boolean_parameters initialize_is_collection_location_parameter initialize_with_public_lat_lng_parameter initialize_with_name_parameter - initialize_with_notes_parameter + initialize_with_obs_notes_parameter add_with_notes_fields_condition(params[:with_notes_fields]) add_join(:comments) if params[:with_comments] add_join(:sequences) if params[:with_sequences] end - def initialize_is_collection_location_parameter - add_boolean_condition( - "observations.is_collection_location IS TRUE", - "observations.is_collection_location IS FALSE", - params[:is_collection_location] - ) - end - - def initialize_with_public_lat_lng_parameter - add_boolean_condition( - "observations.lat IS NOT NULL AND observations.gps_hidden IS FALSE", - "observations.lat IS NULL OR observations.gps_hidden IS TRUE", - params[:with_public_lat_lng] - ) - end - - def initialize_with_name_parameter - genus = Name.ranks[:Genus] - group = Name.ranks[:Group] - add_boolean_condition( - "names.`rank` <= #{genus} or names.`rank` = #{group}", - "names.`rank` > #{genus} and names.`rank` < #{group}", - params[:with_name], - :names - ) - end - - def initialize_with_notes_parameter - add_boolean_condition( - "observations.notes != #{escape(Observation.no_notes_persisted)}", - "observations.notes = #{escape(Observation.no_notes_persisted)}", - params[:with_notes] - ) - end - - def initialize_search_parameters - add_search_condition( - "observations.notes", - params[:notes_has] - ) - add_search_condition( - "CONCAT(comments.summary,COALESCE(comments.comment,''))", - params[:comments_has], - :comments - ) - end - def add_join_to_names add_join(:names) end diff --git a/app/classes/query/project_base.rb b/app/classes/query/project_base.rb index e56de08785..a3cc96ff81 100644 --- a/app/classes/query/project_base.rb +++ b/app/classes/query/project_base.rb @@ -56,14 +56,8 @@ def initialize_boolean_parameters end def initialize_search_parameters - add_search_condition( - "projects.title", - params[:title_has] - ) - add_search_condition( - "projects.summary", - params[:summary_has] - ) + add_search_condition("projects.title", params[:title_has]) + add_search_condition("projects.summary", params[:summary_has]) add_search_condition( "projects.field_slip_prefix", params[:field_slip_prefix_has] diff --git a/app/classes/query/sequence_base.rb b/app/classes/query/sequence_base.rb index 376d49288b..7a2ea90496 100644 --- a/app/classes/query/sequence_base.rb +++ b/app/classes/query/sequence_base.rb @@ -4,6 +4,7 @@ module Query # Methods to validate parameters and initialize Query's which return Sequences class SequenceBase < Query::Base include Query::Initializers::Names + include Query::Initializers::Observations def model Sequence @@ -89,13 +90,14 @@ def search_fields def initialize_association_parameters add_id_condition("sequences.observation_id", params[:observations]) initialize_observers_parameter - initialize_locations_parameter + add_where_condition("observations", params[:locations], :observations) initialize_herbaria_parameter initialize_herbarium_records_parameter initialize_projects_parameter initialize_species_lists_parameter end + # Different because it can take multiple users def initialize_observers_parameter add_id_condition( "observations.user_id", @@ -104,63 +106,10 @@ def initialize_observers_parameter ) end - def initialize_locations_parameter - add_id_condition( - "observations.location_id", - lookup_locations_by_name(params[:locations]), - :observations - ) - end - - def initialize_herbaria_parameter - add_id_condition( - "herbarium_records.herbarium_id", - lookup_herbaria_by_name(params[:herbaria]), - :observations, :observation_herbarium_records, :herbarium_records - ) - end - - def initialize_herbarium_records_parameter - add_id_condition( - "observation_herbarium_records.herbarium_record_id", - lookup_herbarium_records_by_name(params[:herbarium_records]), - :observations, :observation_herbarium_records - ) - end - - def initialize_projects_parameter - add_id_condition( - "project_observations.project_id", - lookup_projects_by_name(params[:projects]), - :observations, :project_observations - ) - end - - def initialize_species_lists_parameter - add_id_condition( - "species_list_observations.species_list_id", - lookup_species_lists_by_name(params[:species_lists]), - :observations, :species_list_observations - ) - end - def initialize_observation_parameters - add_date_condition( - "observations.when", - params[:obs_date], - :observations - ) - add_boolean_condition( - "observations.is_collection_location IS TRUE", - "observations.is_collection_location IS FALSE", - params[:is_collection_location], - :observations - ) - add_range_condition( - "observations.vote_cache", - params[:confidence], - :observations - ) + initialize_obs_date_parameter(:obs_date) + initialize_is_collection_location_parameter + initialize_confidence_parameter end def initialize_exact_match_parameters @@ -173,48 +122,10 @@ def initialize_boolean_parameters initialize_with_images_parameter initialize_with_specimen_parameter initialize_with_name_parameter - initialize_with_obs_notes_parameter + initialize_with_obs_notes_parameter(:with_obs_notes) add_with_notes_fields_condition(params[:with_notes_fields], :observations) end - def initialize_with_images_parameter - add_boolean_condition( - "observations.thumb_image_id IS NOT NULL", - "observations.thumb_image_id IS NULL", - params[:with_images], - :observations - ) - end - - def initialize_with_specimen_parameter - add_boolean_condition( - "observations.specimen IS TRUE", - "observations.specimen IS FALSE", - params[:with_specimen], - :observations - ) - end - - def initialize_with_name_parameter - genus = Name.ranks[:Genus] - group = Name.ranks[:Group] - add_boolean_condition( - "names.`rank` <= #{genus} or names.`rank` = #{group}", - "names.`rank` > #{genus} and names.`rank` < #{group}", - params[:with_name], - :observations, :names - ) - end - - def initialize_with_obs_notes_parameter - add_boolean_condition( - "observations.notes != #{escape(Observation.no_notes_persisted)}", - "observations.notes = #{escape(Observation.no_notes_persisted)}", - params[:with_obs_notes], - :observations - ) - end - def initialize_search_parameters add_search_condition("sequences.locus", params[:locus_has]) add_search_condition("sequences.accession", params[:accession_has]) diff --git a/app/classes/query/species_list_base.rb b/app/classes/query/species_list_base.rb index d24bded017..de786116dd 100644 --- a/app/classes/query/species_list_base.rb +++ b/app/classes/query/species_list_base.rb @@ -38,7 +38,7 @@ def initialize_flavor add_pattern_condition add_ids_condition add_by_user_condition("species_lists") - add_for_project_condition + add_for_project_condition(:project_species_lists) initialize_name_parameters(:species_list_observations, :observations) initialize_association_parameters initialize_boolean_parameters @@ -53,32 +53,11 @@ def add_pattern_condition super end - def add_for_project_condition - return if params[:project].blank? - - project = find_cached_parameter_instance(Project, :project) - @title_tag = :query_title_for_project - @title_args[:project] = project.title - where << "project_species_lists.project_id = '#{params[:project]}'" - add_join("project_species_lists") - end - def initialize_association_parameters - initialize_at_location_parameter - add_where_condition("species_lists", params[:locations]) - add_id_condition( - "project_species_lists.project_id", - lookup_projects_by_name(params[:projects]), - :project_species_lists - ) - end - - def initialize_at_location_parameter - return unless params[:location] - - location = find_cached_parameter_instance(Location, :location) - title_args[:location] = location.display_name - where << "species_lists.location_id = '#{location.id}'" + add_at_location_condition + add_where_condition(:species_lists, params[:locations]) + initialize_projects_parameter(:project_species_lists, + [:project_species_lists]) end def initialize_boolean_parameters @@ -99,14 +78,8 @@ def initialize_at_where_parameter end def initialize_search_parameters - add_search_condition( - "species_lists.title", - params[:title_has] - ) - add_search_condition( - "species_lists.notes", - params[:notes_has] - ) + add_search_condition("species_lists.title", params[:title_has]) + add_search_condition("species_lists.notes", params[:notes_has]) add_search_condition( "CONCAT(comments.summary,COALESCE(comments.comment,''))", params[:comments_has], diff --git a/app/models/field_slip.rb b/app/models/field_slip.rb index 469e075eda..a63e151aa2 100644 --- a/app/models/field_slip.rb +++ b/app/models/field_slip.rb @@ -9,6 +9,13 @@ class FieldSlip < AbstractModel belongs_to :user default_scope { order(:code) } + scope :by_user, lambda { |user| + where(user_id: user.id).distinct + } + scope :for_project, lambda { |project| + where(project_id: project.id).distinct + } + validates :code, uniqueness: true validates :code, presence: true validate do |field_slip| diff --git a/test/models/query_test.rb b/test/models/query_test.rb index c46939eaa7..3cf794fc3b 100644 --- a/test/models/query_test.rb +++ b/test/models/query_test.rb @@ -1251,6 +1251,21 @@ def test_external_link_all :ExternalLink, :all, url: "iNaturalist") end + def test_field_slip_all + expect = FieldSlip.all.sort_by(&:date) + assert_query(expect, :FieldSlip, :all) + end + + def test_field_slip_by_user + expect = FieldSlip.by_user(users(:mary)).sort_by(&:date) + assert_query(expect, :FieldSlip, :all, by_user: mary) + end + + def test_field_slip_for_project + expect = FieldSlip.for_project(projects(:eol_project)).sort_by(&:date) + assert_query(expect, :FieldSlip, :all, project: projects(:eol_project)) + end + def test_glossary_term_all expect = GlossaryTerm.all.sort_by(&:name) assert_query(expect, :GlossaryTerm, :all) @@ -2634,6 +2649,14 @@ def test_observation_for_project :Observation, :all, project: projects(:bolete_project)) end + def test_observation_for_project_projects_equivalence + qu1 = Query.lookup_and_save(:Observation, :all, + project: projects(:bolete_project)) + qu2 = Query.lookup_and_save(:Observation, :all, + projects: projects(:bolete_project).id.to_s) + assert_equal(qu1.results, qu2.results) + end + def test_observation_in_set obs_set_ids = [observations(:unknown_with_no_naming).id, observations(:minimal_unknown_obs).id,