diff --git a/app/classes/query/image_with_observations.rb b/app/classes/query/image_with_observations.rb index ffc86ef401..dc42f2db22 100644 --- a/app/classes/query/image_with_observations.rb +++ b/app/classes/query/image_with_observations.rb @@ -3,38 +3,25 @@ module Query # Query's for Images where Observation meets specified conditions class ImageWithObservations < Query::ImageBase - include Query::Initializers::ContentFilters include Query::Initializers::Names + include Query::Initializers::Observations + include Query::Initializers::Locations + include Query::Initializers::ContentFilters include Query::Initializers::ObservationQueryDescriptions def parameter_declarations super.merge( - old_title?: :string, - old_by?: :string, - ids?: [Observation], - herbaria?: [:string], - location?: Location, - user_where?: :string, - project?: Project, - species_list?: SpeciesList, - is_collection_location?: :boolean, - with_public_lat_lng?: :boolean, - with_name?: :boolean, - with_comments?: { boolean: [true] }, - with_sequences?: { boolean: [true] }, - with_notes_fields?: [:string], - comments_has?: :string, - north?: :float, - south?: :float, - east?: :float, - west?: :float - ).merge(content_filter_parameter_declarations(Observation)). - merge(consensus_parameter_declarations) + obs_ids?: [Observation] + ).merge(observations_parameter_declarations). + merge(observations_coercion_parameter_declarations). + merge(bounding_box_parameter_declarations). + merge(content_filter_parameter_declarations(Observation)). + merge(naming_consensus_parameter_declarations) end def initialize_flavor add_join(:observation_images, :observations) - add_ids_condition("observations") + 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]) @@ -150,7 +137,7 @@ def default_order end def coerce_into_observation_query - Query.lookup(:Observation, :all, params_with_old_by_restored) + Query.lookup(:Observation, :all, params_back_to_observation_params) end def title diff --git a/app/classes/query/initializers/descriptions.rb b/app/classes/query/initializers/descriptions.rb index e11eb78400..8a8ed65245 100644 --- a/app/classes/query/initializers/descriptions.rb +++ b/app/classes/query/initializers/descriptions.rb @@ -17,6 +17,30 @@ def descriptions_parameter_declarations } end + def descriptions_coercion_parameter_declarations + { + old_title?: :string, + old_by?: :string, + by_author?: User + } + 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 + def initialize_description_parameters(type = :name) initialize_with_default_desc_parameter(type) initialize_join_desc_parameter(type) diff --git a/app/classes/query/initializers/locations.rb b/app/classes/query/initializers/locations.rb new file mode 100644 index 0000000000..7aa5738a1d --- /dev/null +++ b/app/classes/query/initializers/locations.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Query + module Initializers + # initializing methods inherited by all Query's for Locations + module Locations + def bounding_box_parameter_declarations + { + north?: :float, + south?: :float, + east?: :float, + west?: :float + } + end + end + end +end diff --git a/app/classes/query/initializers/names.rb b/app/classes/query/initializers/names.rb index 6dbc96ed11..bab0384e06 100644 --- a/app/classes/query/initializers/names.rb +++ b/app/classes/query/initializers/names.rb @@ -14,31 +14,17 @@ def names_parameter_declarations } end - def consensus_parameter_declarations + def naming_consensus_parameter_declarations { include_all_name_proposals?: :boolean, exclude_consensus?: :boolean } end - def names_parameters - { - names: params[:names], - include_synonyms: params[:include_synonyms], - include_subtaxa: params[:include_subtaxa], - include_immediate_subtaxa: params[:include_immediate_subtaxa], - exclude_original_names: params[:exclude_original_names] - } - end - def initialize_name_parameters(*joins) return force_empty_results if irreconcilable_name_parameters? - table = if params[:include_all_name_proposals] - "namings" - else - "observations" - end + table = params[:include_all_name_proposals] ? "namings" : "observations" column = "#{table}.name_id" ids = lookup_names_by_name(names_parameters) add_id_condition(column, ids, *joins) @@ -55,6 +41,14 @@ def initialize_name_parameters_for_name_queries add_id_condition("names.id", lookup_names_by_name(names_parameters)) end + # Copy only the names_parameters into a name_params hash we use here. + def names_parameters + name_params = names_parameter_declarations.dup + name_params.transform_keys! { |k| k.to_s.chomp("?").to_sym } + name_params.each_key { |k| name_params[k] = params[k] } + name_params + end + # ------------------------------------------------------------------------ private diff --git a/app/classes/query/initializers/observations.rb b/app/classes/query/initializers/observations.rb new file mode 100644 index 0000000000..974051c4b0 --- /dev/null +++ b/app/classes/query/initializers/observations.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module Query + module Initializers + # initializing methods inherited by all Query's for Observations + module Observations + def observations_parameter_declarations + { + notes_has?: :string, + with_notes_fields?: [:string], + comments_has?: :string, + herbaria?: [:string], + user_where?: :string, + by_user?: User, + location?: Location, + locations?: [:string], + project?: Project, + projects?: [:string], + species_list?: SpeciesList, + species_lists?: [:string], + + # boolean + with_comments?: { boolean: [true] }, + with_public_lat_lng?: :boolean, + with_name?: :boolean, + with_notes?: :boolean, + with_sequences?: { boolean: [true] }, + is_collection_location?: :boolean, + + # numeric + confidence?: [:float] + } + end + + def observations_coercion_parameter_declarations + { + old_title?: :string, + old_by?: :string, + date?: [:date] + } + end + + def params_out_to_with_observations_params(pargs) + return pargs if pargs[:ids].blank? + + pargs[:obs_ids] = pargs.delete(:ids) + pargs + end + + def params_back_to_observation_params + pargs = params_with_old_by_restored + return pargs if pargs[:obs_ids].blank? + + pargs[:ids] = pargs.delete(:obs_ids) + pargs + end + end + end +end diff --git a/app/classes/query/location_base.rb b/app/classes/query/location_base.rb index 1929d57732..5a60bd1ba7 100644 --- a/app/classes/query/location_base.rb +++ b/app/classes/query/location_base.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Query::LocationBase < Query::Base + include Query::Initializers::Locations + include Query::Initializers::Descriptions include Query::Initializers::ContentFilters include Query::Initializers::AdvancedSearch @@ -16,13 +18,10 @@ def parameter_declarations by_user?: User, by_editor?: User, users?: [User], - north?: :float, - south?: :float, - east?: :float, - west?: :float, pattern?: :string, regexp?: :string - ).merge(content_filter_parameter_declarations(Location)). + ).merge(bounding_box_parameter_declarations). + merge(content_filter_parameter_declarations(Location)). merge(advanced_search_parameter_declarations) end diff --git a/app/classes/query/location_description_all.rb b/app/classes/query/location_description_all.rb index 4f0c0988ce..f80d402458 100644 --- a/app/classes/query/location_description_all.rb +++ b/app/classes/query/location_description_all.rb @@ -13,6 +13,7 @@ def initialize_flavor end def coerce_into_location_query - Query.lookup(:Location, :with_descriptions, params_plus_old_by) + pargs = params_out_to_with_descriptions_params + Query.lookup(:Location, :with_descriptions, pargs) end end diff --git a/app/classes/query/location_description_base.rb b/app/classes/query/location_description_base.rb index baa0e7873c..44bc450e55 100644 --- a/app/classes/query/location_description_base.rb +++ b/app/classes/query/location_description_base.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Query::LocationDescriptionBase < Query::Base + include Query::Initializers::Descriptions + def model LocationDescription end diff --git a/app/classes/query/location_with_descriptions.rb b/app/classes/query/location_with_descriptions.rb index 1220f1dec6..a6970c7328 100644 --- a/app/classes/query/location_with_descriptions.rb +++ b/app/classes/query/location_with_descriptions.rb @@ -3,11 +3,8 @@ class Query::LocationWithDescriptions < Query::LocationBase def parameter_declarations super.merge( - ids?: [LocationDescription], - old_title?: :string, - old_by?: :string, - by_author?: User - ) + desc_ids?: [LocationDescription] + ).merge(descriptions_coercion_parameter_declarations) end def initialize_flavor @@ -20,12 +17,15 @@ def initialize_flavor end def add_ids_condition - return unless params[:ids] + 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) - initialize_in_set_flavor("location_descriptions") end def add_by_user_condition @@ -59,6 +59,6 @@ def add_by_editor_condition end def coerce_into_location_description_query - Query.lookup(:LocationDescription, :all, params_with_old_by_restored) + Query.lookup(:LocationDescription, :all, params_back_to_description_params) end end diff --git a/app/classes/query/location_with_observations.rb b/app/classes/query/location_with_observations.rb index efa6cb1b8e..cab7122f39 100644 --- a/app/classes/query/location_with_observations.rb +++ b/app/classes/query/location_with_observations.rb @@ -3,42 +3,24 @@ module Query # Query's for Locations where Observation meets specified conditions class LocationWithObservations < Query::LocationBase - include Query::Initializers::ContentFilters include Query::Initializers::Names + include Query::Initializers::Observations + include Query::Initializers::ContentFilters include Query::Initializers::ObservationQueryDescriptions def parameter_declarations super.merge( - old_by?: :string, - date?: [:date], - ids?: [Observation], - old_title?: :string, - locations?: [:string], - location?: Location, - user_where?: :string, - project?: Project, - projects?: [:string], - species_list?: SpeciesList, - species_lists?: [:string], - herbaria?: [:string], - confidence?: [:float], - is_collection_location?: :boolean, - with_public_lat_lng?: :boolean, - with_name?: :boolean, - with_comments?: { boolean: [true] }, - with_sequences?: { boolean: [true] }, - with_notes?: :boolean, - with_notes_fields?: [:string], - notes_has?: :string, - comments_has?: :string - ).merge(content_filter_parameter_declarations(Observation)). + obs_ids?: [Observation] + ).merge(observations_parameter_declarations). + merge(observations_coercion_parameter_declarations). + merge(content_filter_parameter_declarations(Observation)). merge(names_parameter_declarations). - merge(consensus_parameter_declarations) + merge(naming_consensus_parameter_declarations) end def initialize_flavor add_join(:observations) - add_ids_condition("observations") + add_ids_condition add_owner_and_time_stamp_conditions("observations") add_by_user_condition("observations") add_date_condition("observations.when", params[:date]) @@ -52,13 +34,16 @@ def initialize_flavor super end - def add_ids_condition(table) - return unless params[:ids] + 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" - initialize_in_set_flavor(table) end def add_where_conditions @@ -167,7 +152,7 @@ def initialize_search_parameters end def coerce_into_observation_query - Query.lookup(:Observation, :all, params_with_old_by_restored) + Query.lookup(:Observation, :all, params_back_to_observation_params) end def title diff --git a/app/classes/query/modules/conditions.rb b/app/classes/query/modules/conditions.rb index 68e910ae7a..868b9cee18 100644 --- a/app/classes/query/modules/conditions.rb +++ b/app/classes/query/modules/conditions.rb @@ -99,10 +99,13 @@ def add_indexed_enum_condition(col, vals, allowed, *) add_joins(*) end - def add_ids_condition(table = model.table_name) - return if params[:ids].nil? # [] is valid + # Generalized so the param can be :obs_ids or :desc_ids + def add_ids_condition(table = model.table_name, ids = :ids) + return if params[ids].nil? # [] is valid - initialize_in_set_flavor(table) + set = clean_id_set(params[ids]) + @where << "#{table}.id IN (#{set})" + self.order = "FIND_IN_SET(#{table}.id,'#{set}') ASC" @title_tag = :query_title_in_set.t(type: table.singularize.to_sym) # @title_args[:by] = :query_sorted_by.t(field: :original_name) @@ -110,13 +113,6 @@ def add_ids_condition(table = model.table_name) # :query_title_in_set.t(type: table.singularize.to_sym) end - # move this above when all in_set flavors converted - def initialize_in_set_flavor(table = model.table_name) - set = clean_id_set(params[:ids]) - @where << "#{table}.id IN (#{set})" - self.order = "FIND_IN_SET(#{table}.id,'#{set}') ASC" - end - def add_id_condition(col, ids, *) return if ids.empty? diff --git a/app/classes/query/name_description_all.rb b/app/classes/query/name_description_all.rb index d5a9b53af7..49816d068e 100644 --- a/app/classes/query/name_description_all.rb +++ b/app/classes/query/name_description_all.rb @@ -13,6 +13,7 @@ def initialize_flavor end def coerce_into_name_query - Query.lookup(:Name, :with_descriptions, params_plus_old_by) + pargs = params_out_to_with_descriptions_params + Query.lookup(:Name, :with_descriptions, pargs) end end diff --git a/app/classes/query/name_description_base.rb b/app/classes/query/name_description_base.rb index 2e33e86e78..f030e54886 100644 --- a/app/classes/query/name_description_base.rb +++ b/app/classes/query/name_description_base.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Query::NameDescriptionBase < Query::Base + include Query::Initializers::Descriptions + def model NameDescription end diff --git a/app/classes/query/name_with_descriptions.rb b/app/classes/query/name_with_descriptions.rb index 571f2a9221..fbf79a453f 100644 --- a/app/classes/query/name_with_descriptions.rb +++ b/app/classes/query/name_with_descriptions.rb @@ -3,11 +3,8 @@ class Query::NameWithDescriptions < Query::NameBase def parameter_declarations super.merge( - ids?: [NameDescription], - old_title?: :string, - old_by?: :string, - by_author?: User - ) + desc_ids?: [NameDescription] + ).merge(descriptions_coercion_parameter_declarations) end def initialize_flavor @@ -20,12 +17,15 @@ def initialize_flavor end def add_ids_condition - return unless params[:ids] + 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) - initialize_in_set_flavor("name_descriptions") end def add_by_user_condition @@ -59,6 +59,6 @@ def add_by_editor_condition end def coerce_into_name_description_query - Query.lookup(:NameDescription, :all, params_with_old_by_restored) + Query.lookup(:NameDescription, :all, params_back_to_description_params) end end diff --git a/app/classes/query/name_with_observations.rb b/app/classes/query/name_with_observations.rb index 7b15482b20..b9084e3c3e 100644 --- a/app/classes/query/name_with_observations.rb +++ b/app/classes/query/name_with_observations.rb @@ -3,40 +3,25 @@ module Query # Query's for Names where Observations meet specified conditions class NameWithObservations < Query::NameBase - include Query::Initializers::ContentFilters include Query::Initializers::Names + include Query::Initializers::Observations + include Query::Initializers::Locations + include Query::Initializers::ContentFilters include Query::Initializers::ObservationQueryDescriptions def parameter_declarations super.merge( - old_title?: :string, - old_by?: :string, - date?: [:date], - ids?: [Observation], - by_user?: User, - project?: Project, - projects?: [:string], - species_list?: SpeciesList, - herbaria?: [:string], - confidence?: [:float], - location?: Location, - user_where?: :string, - is_collection_location?: :boolean, - with_public_lat_lng?: :boolean, - with_name?: :boolean, - with_sequences?: { boolean: [true] }, - with_notes_fields?: [:string], - north?: :float, - south?: :float, - east?: :float, - west?: :float - ).merge(content_filter_parameter_declarations(Observation)). - merge(consensus_parameter_declarations) + obs_ids?: [Observation] + ).merge(observations_parameter_declarations). + merge(observations_coercion_parameter_declarations). + merge(bounding_box_parameter_declarations). + merge(content_filter_parameter_declarations(Observation)). + merge(naming_consensus_parameter_declarations) end def initialize_flavor add_join(:observations) - add_ids_condition("observations") + 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]) @@ -148,7 +133,7 @@ def initialize_search_parameters end def coerce_into_observation_query - Query.lookup(:Observation, :all, params_with_old_by_restored) + Query.lookup(:Observation, :all, params_back_to_observation_params) end def title diff --git a/app/classes/query/observation_all.rb b/app/classes/query/observation_all.rb index bc85e34137..db13753ef3 100644 --- a/app/classes/query/observation_all.rb +++ b/app/classes/query/observation_all.rb @@ -23,11 +23,9 @@ def coerce_into_name_query def do_coerce(new_model) is_search = params[:pattern].present? || advanced_search_params.any? { |key| params[key].present? } - pargs = if is_search - add_old_title(params_plus_old_by) - else - params_plus_old_by - end + pargs = is_search ? add_old_title(params_plus_old_by) : params_plus_old_by + # transform :ids to :obs_ids + pargs = params_out_to_with_observations_params(pargs) Query.lookup(new_model, :with_observations, pargs) end diff --git a/app/classes/query/observation_base.rb b/app/classes/query/observation_base.rb index da30e1f310..dabb651c0f 100644 --- a/app/classes/query/observation_base.rb +++ b/app/classes/query/observation_base.rb @@ -2,10 +2,11 @@ module Query # methods for initializing Query's for Observations - # rubocop:disable Metrics/ClassLength class ObservationBase < Query::Base - include Query::Initializers::ContentFilters include Query::Initializers::Names + include Query::Initializers::Observations + include Query::Initializers::Locations + include Query::Initializers::ContentFilters include Query::Initializers::AdvancedSearch def model @@ -14,13 +15,14 @@ def model def parameter_declarations super.merge(local_parameter_declarations). + merge(observations_parameter_declarations). + merge(bounding_box_parameter_declarations). merge(content_filter_parameter_declarations(Observation)). merge(names_parameter_declarations). - merge(consensus_parameter_declarations). + merge(naming_consensus_parameter_declarations). merge(advanced_search_parameter_declarations) end - # rubocop:disable Metrics/MethodLength def local_parameter_declarations { # dates/times @@ -29,19 +31,8 @@ def local_parameter_declarations updated_at?: [:time], ids?: [Observation], - comments_has?: :string, - with_notes_fields?: [:string], - herbaria?: [:string], herbarium_records?: [:string], - location?: Location, - user_where?: :string, - locations?: [:string], - notes_has?: :string, - project?: Project, - projects?: [:string], project_lists?: [:string], - species_list?: SpeciesList, - species_lists?: [:string], by_user?: User, by_editor?: User, # for coercions from name/location users?: [User], @@ -50,25 +41,9 @@ def local_parameter_declarations regexp?: :string, # for coercions from location needs_naming?: :boolean, in_clade?: :string, - in_region?: :string, - - # numeric - confidence?: [:float], - east?: :float, - north?: :float, - south?: :float, - west?: :float, - - # boolean - with_comments?: { boolean: [true] }, - with_public_lat_lng?: :boolean, - with_name?: :boolean, - with_notes?: :boolean, - with_sequences?: { boolean: [true] }, - is_collection_location?: :boolean + in_region?: :string } end - # rubocop:enable Metrics/MethodLength # rubocop:disable Metrics/AbcSize def initialize_flavor @@ -342,5 +317,4 @@ def self.default_order "date" end end - # rubocop:enable Metrics/ClassLength end diff --git a/test/models/query_test.rb b/test/models/query_test.rb index a301b2a9b4..c46939eaa7 100644 --- a/test/models/query_test.rb +++ b/test/models/query_test.rb @@ -913,370 +913,187 @@ def test_basic_coerce end def test_observation_image_coercion + query_a = [] + # Several observation queries can be turned into image queries. - q1a = Query.lookup_and_save(:Observation, :all, by: :id) - q2a = Query.lookup_and_save(:Observation, :all, by_user: mary.id) - q3a = Query.lookup_and_save( + query_a[0] = Query.lookup_and_save(:Observation, :all, by: :id) + query_a[1] = Query.lookup_and_save(:Observation, :all, by_user: mary.id) + query_a[2] = Query.lookup_and_save( :Observation, :all, species_list: species_lists(:first_species_list).id ) - q5a = Query.lookup_and_save(:Observation, :all, - ids: [ - observations(:detailed_unknown_obs).id, - observations(:agaricus_campestris_obs).id, - observations(:agaricus_campestras_obs).id - ]) - # removed q6a which searched for "somewhere else" in the notes - # q6a = Query.lookup_and_save(:Observation, :all, - # pattern: '"somewhere else"') - q7a = Query.lookup_and_save(:Observation, :all, - user_where: "glendale") - q8a = Query.lookup_and_save(:Observation, :all, - location: locations(:burbank)) - q9a = Query.lookup_and_save(:Observation, :all, - user_where: "california") + query_a[3] = Query.lookup_and_save( + :Observation, :all, ids: [observations(:detailed_unknown_obs).id, + observations(:agaricus_campestris_obs).id, + observations(:agaricus_campestras_obs).id] + ) + query_a[4] = Query.lookup_and_save(:Observation, :all, + user_where: "glendale") + query_a[5] = Query.lookup_and_save(:Observation, :all, + location: locations(:burbank)) + query_a[6] = Query.lookup_and_save(:Observation, :all, + user_where: "california") + # removed query_a[7] which searched for "somewhere else" in the notes + # query_a[7] = Query.lookup_and_save(:Observation, :all, + # pattern: '"somewhere else"') assert_equal(7, QueryRecord.count) - # Try coercing them all. - assert(q1b = q1a.coerce(:Image)) - assert(q2b = q2a.coerce(:Image)) - assert(q3b = q3a.coerce(:Image)) - assert(q5b = q5a.coerce(:Image)) - # assert(q6b = q6a.coerce(:Image)) - assert(q7b = q7a.coerce(:Image)) - assert(q8b = q8a.coerce(:Image)) - assert(q9b = q9a.coerce(:Image)) - - # They should all be new records - assert(q1b.record.new_record?) - assert_save(q1b) - assert(q2b.record.new_record?) - assert_save(q2b) - assert(q3b.record.new_record?) - assert_save(q3b) - assert(q5b.record.new_record?) - assert_save(q5b) - # assert(q6b.record.new_record?) - # assert_save(q6b) - assert(q7b.record.new_record?) - assert_save(q7b) - assert(q8b.record.new_record?) - assert_save(q8b) - assert(q9b.record.new_record?) - assert_save(q9b) - - # Check their descriptions. - assert_equal("Image", q1b.model.to_s) - assert_equal("Image", q2b.model.to_s) - assert_equal("Image", q3b.model.to_s) - assert_equal("Image", q5b.model.to_s) - # assert_equal("Image", q6b.model.to_s) - assert_equal("Image", q7b.model.to_s) - assert_equal("Image", q8b.model.to_s) - assert_equal("Image", q9b.model.to_s) - - assert_equal(:with_observations, q1b.flavor) - assert_equal(:with_observations, q2b.flavor) - assert_equal(:with_observations, q3b.flavor) - assert_equal(:with_observations, q5b.flavor) - # assert_equal(:with_observations, q6b.flavor) - assert_equal(:with_observations, q7b.flavor) - assert_equal(:with_observations, q8b.flavor) - assert_equal(:with_observations, q9b.flavor) - - # Now try to coerce them back to Observation. - assert(q1c = q1b.coerce(:Observation)) - assert(q2c = q2b.coerce(:Observation)) - assert(q3c = q3b.coerce(:Observation)) - assert(q5c = q5b.coerce(:Observation)) - # assert(q6c = q6b.coerce(:Observation)) - assert(q7c = q7b.coerce(:Observation)) - assert(q8c = q8b.coerce(:Observation)) - assert(q9c = q9b.coerce(:Observation)) - - # Only some should be new. - assert_not(q1c.record.new_record?) - assert_equal(q1a, q1c) - assert_not(q2c.record.new_record?) - assert_equal(q2a, q2c) - assert_not(q3c.record.new_record?) - assert_equal(q3a, q3c) - assert_not(q5c.record.new_record?) - assert_equal(q5a, q5c) - # assert(q6c.record.new_record?) # (converted to in_set) - assert_not(q7c.record.new_record?) - assert_equal(q7a, q7c) - assert_not(q8c.record.new_record?) - assert_equal(q8a, q8c) - assert_not(q9c.record.new_record?) - assert_equal(q9a, q9c) + observation_coercion_assertions(query_a, :Image) end def test_observation_location_coercion + query_a = [] + # Almost any query on observations should be mappable, i.e. coercable into # a query on those observations' locations. - q1a = Query.lookup_and_save(:Observation, :all, by: :id) - q2a = Query.lookup_and_save(:Observation, :all, by_user: mary.id) - q3a = Query.lookup_and_save( + query_a[0] = Query.lookup_and_save(:Observation, :all, by: :id) + query_a[1] = Query.lookup_and_save(:Observation, :all, by_user: mary.id) + query_a[2] = Query.lookup_and_save( :Observation, :all, species_list: species_lists(:first_species_list).id ) - q5a = Query.lookup_and_save(:Observation, :all, - ids: - [observations(:detailed_unknown_obs).id, - observations(:agaricus_campestris_obs).id, - observations(:agaricus_campestras_obs).id]) - # q6a = Query.lookup_and_save(:Observation, :all, - # pattern: '"somewhere else"') - q7a = Query.lookup_and_save(:Observation, :all, - user_where: "glendale") - q8a = Query.lookup_and_save(:Observation, :all, - location: locations(:burbank)) - q9a = Query.lookup_and_save(:Observation, :all, - user_where: "california") + query_a[3] = Query.lookup_and_save( + :Observation, :all, ids: [observations(:detailed_unknown_obs).id, + observations(:agaricus_campestris_obs).id, + observations(:agaricus_campestras_obs).id] + ) + query_a[4] = Query.lookup_and_save(:Observation, :all, + user_where: "glendale") + query_a[5] = Query.lookup_and_save(:Observation, :all, + location: locations(:burbank)) + query_a[6] = Query.lookup_and_save(:Observation, :all, + user_where: "california") + # query_a[7] = Query.lookup_and_save(:Observation, :all, + # pattern: '"somewhere else"') assert_equal(7, QueryRecord.count) - # Try coercing them all. - assert(q1b = q1a.coerce(:Location)) - assert(q2b = q2a.coerce(:Location)) - assert(q3b = q3a.coerce(:Location)) - assert(q5b = q5a.coerce(:Location)) - # assert(q6b = q6a.coerce(:Location)) - assert(q7b = q7a.coerce(:Location)) - assert(q8b = q8a.coerce(:Location)) - assert(q9b = q9a.coerce(:Location)) - - # They should all be new records - assert(q1b.record.new_record?) - assert_save(q1b) - assert(q2b.record.new_record?) - assert_save(q2b) - assert(q3b.record.new_record?) - assert_save(q3b) - assert(q5b.record.new_record?) - assert_save(q5b) - # assert(q6b.record.new_record?) - # assert_save(q6b) - assert(q7b.record.new_record?) - assert_save(q7b) - assert(q8b.record.new_record?) - assert_save(q8b) - assert(q9b.record.new_record?) - assert_save(q9b) - - # Check their descriptions. - assert_equal("Location", q1b.model.to_s) - assert_equal("Location", q2b.model.to_s) - assert_equal("Location", q3b.model.to_s) - assert_equal("Location", q5b.model.to_s) - # assert_equal("Location", q6b.model.to_s) - assert_equal("Location", q7b.model.to_s) - assert_equal("Location", q8b.model.to_s) - assert_equal("Location", q9b.model.to_s) - - assert_equal(:with_observations, q1b.flavor) - assert_equal(:with_observations, q2b.flavor) - assert_equal(:with_observations, q3b.flavor) - assert_equal(:with_observations, q5b.flavor) - # assert_equal(:with_observations, q6b.flavor) - assert_equal(:with_observations, q7b.flavor) - assert_equal(:with_observations, q8b.flavor) - assert_equal(:with_observations, q9b.flavor) - - assert_equal({ old_by: "id" }, q1b.params) - assert_equal({ by_user: mary.id }, q2b.params) - assert_equal({ species_list: species_lists(:first_species_list).id }, - q3b.params) + query_b = observation_coercion_assertions(query_a, :Location) + # Now, check the parameters of those coerced queries. + assert_equal({ old_by: "id" }, query_b[0].params) + assert_equal({ by_user: mary.id }, query_b[1].params) + assert_equal({ species_list: species_lists(:first_species_list).id }, + query_b[2].params) assert_equal([observations(:detailed_unknown_obs).id, observations(:agaricus_campestris_obs).id, observations(:agaricus_campestras_obs).id], - q5b.params[:ids]) - assert_equal(1, q5b.params.keys.length) - # assert_equal(2, q6b.params.keys.length) + query_b[3].params[:obs_ids]) + assert_equal(1, query_b[3].params.keys.length) + assert_equal("glendale", query_b[4].params[:user_where]) + assert_equal(2, query_b[4].params.keys.length) + assert_equal(locations(:burbank).id, query_b[5].params[:location]) + assert_equal(1, query_b[5].params.keys.length) + assert_equal("california", query_b[6].params[:user_where]) + assert_equal(2, query_b[6].params.keys.length) + # assert_equal(2, query_b[7].params.keys.length) # assert_equal([observations(:strobilurus_diminutivus_obs).id, # observations(:agaricus_campestros_obs).id, # observations(:agaricus_campestras_obs).id, # observations(:agaricus_campestrus_obs).id], - # q6b.params[:ids]) + # query_b[7].params[:obs_ids]) # assert_match(/Observations.*Matching.*somewhere.*else/, - # q6b.params[:old_title]) - assert_equal("glendale", q7b.params[:user_where]) - assert_equal(2, q7b.params.keys.length) # advanced search gets old_title - assert_equal(locations(:burbank).id, q8b.params[:location]) - assert_equal(1, q8b.params.keys.length) - assert_equal("california", q9b.params[:user_where]) - assert_equal(2, q9b.params.keys.length) # advanced search gets old_title - - # Now try to coerce them back to Observation. - assert(q1c = q1b.coerce(:Observation)) - assert(q2c = q2b.coerce(:Observation)) - assert(q3c = q3b.coerce(:Observation)) - assert(q5c = q5b.coerce(:Observation)) - # assert(q6c = q6b.coerce(:Observation)) - assert(q7c = q7b.coerce(:Observation)) - assert(q8c = q8b.coerce(:Observation)) - assert(q9c = q9b.coerce(:Observation)) - - # Only some should be new. - assert_not(q1c.record.new_record?) - assert_equal(q1a, q1c) - assert_not(q2c.record.new_record?) - assert_equal(q2a, q2c) - assert_not(q3c.record.new_record?) - assert_equal(q3a, q3c) - assert_not(q5c.record.new_record?) - assert_equal(q5a, q5c) - # assert(q6c.record.new_record?) # (converted to in_set) - assert_not(q7c.record.new_record?) - assert_not(q8c.record.new_record?) - assert_not(q9c.record.new_record?) + # query_b[7].params[:old_title]) end def test_observation_name_coercion + query_a = [] + # Several observation queries can be turned into name queries. - q1a = Query.lookup_and_save(:Observation, :all, by: :id) - q2a = Query.lookup_and_save(:Observation, :all, by_user: mary.id) - q3a = Query.lookup_and_save( + query_a[0] = Query.lookup_and_save(:Observation, :all, by: :id) + query_a[1] = Query.lookup_and_save(:Observation, :all, by_user: mary.id) + query_a[2] = Query.lookup_and_save( :Observation, :all, species_list: species_lists(:first_species_list).id ) - q5a = Query.lookup_and_save(:Observation, :all, - ids: [ - observations(:detailed_unknown_obs).id, - observations(:agaricus_campestris_obs).id, - observations(:agaricus_campestras_obs).id - ]) - # q6a = Query.lookup_and_save(:Observation, :all, + query_a[3] = Query.lookup_and_save( + :Observation, :all, ids: [observations(:detailed_unknown_obs).id, + observations(:agaricus_campestris_obs).id, + observations(:agaricus_campestras_obs).id] + ) + # qa[4] = Query.lookup_and_save(:Observation, :all, # pattern: '"somewhere else"') - q7a = Query.lookup_and_save(:Observation, :all, - user_where: "glendale") - q8a = Query.lookup_and_save(:Observation, :all, - location: locations(:burbank)) - q9a = Query.lookup_and_save(:Observation, :all, - user_where: "california") + query_a[4] = Query.lookup_and_save(:Observation, :all, + user_where: "glendale") + query_a[5] = Query.lookup_and_save(:Observation, :all, + location: locations(:burbank)) + query_a[6] = Query.lookup_and_save(:Observation, :all, + user_where: "california") assert_equal(7, QueryRecord.count) - # Try coercing them all. - assert(q1b = q1a.coerce(:Name)) - assert(q2b = q2a.coerce(:Name)) - assert(q3b = q3a.coerce(:Name)) - assert(q5b = q5a.coerce(:Name)) - # assert(q6b = q6a.coerce(:Name)) - assert(q7b = q7a.coerce(:Name)) - assert(q8b = q8a.coerce(:Name)) - assert(q9b = q9a.coerce(:Name)) - - # They should all be new records - assert(q1b.record.new_record?) - assert_save(q1b) - assert(q2b.record.new_record?) - assert_save(q2b) - assert(q3b.record.new_record?) - assert_save(q3b) - assert(q5b.record.new_record?) - assert_save(q5b) - # assert(q6b.record.new_record?) - # assert_save(q6b) - assert(q7b.record.new_record?) - assert_save(q7b) - assert(q8b.record.new_record?) - assert_save(q8b) - assert(q9b.record.new_record?) - assert_save(q9b) - - # Check their descriptions. - assert_equal("Name", q1b.model.to_s) - assert_equal("Name", q2b.model.to_s) - assert_equal("Name", q3b.model.to_s) - assert_equal("Name", q5b.model.to_s) - # assert_equal("Name", q6b.model.to_s) - assert_equal("Name", q7b.model.to_s) - assert_equal("Name", q8b.model.to_s) - assert_equal("Name", q9b.model.to_s) - - assert_equal(:with_observations, q1b.flavor) - assert_equal(:with_observations, q2b.flavor) - assert_equal(:with_observations, q3b.flavor) - assert_equal(:with_observations, q5b.flavor) - # assert_equal(:with_observations, q6b.flavor) - assert_equal(:with_observations, q7b.flavor) - assert_equal(:with_observations, q8b.flavor) - assert_equal(:with_observations, q9b.flavor) - - # Now try to coerce them back to Observation. - assert(q1c = q1b.coerce(:Observation)) - assert(q2c = q2b.coerce(:Observation)) - assert(q3c = q3b.coerce(:Observation)) - assert(q5c = q5b.coerce(:Observation)) - # assert(q6c = q6b.coerce(:Observation)) - assert(q7c = q7b.coerce(:Observation)) - assert(q8c = q8b.coerce(:Observation)) - assert(q9c = q9b.coerce(:Observation)) - - # Only some should be new. - assert_not(q1c.record.new_record?) - assert_equal(q1a, q1c) - assert_not(q2c.record.new_record?) - assert_equal(q2a, q2c) - assert_not(q3c.record.new_record?) - assert_equal(q3a, q3c) - assert_not(q5c.record.new_record?) - assert_equal(q5a, q5c) - # assert(q6c.record.new_record?) # (converted to in_set) - assert_not(q7c.record.new_record?) - assert_equal(q7a, q7c) - assert_not(q8c.record.new_record?) - assert_equal(q8a, q8c) - assert_not(q9c.record.new_record?) - assert_equal(q9a, q9c) - end - - def test_description_coercion + observation_coercion_assertions(query_a, :Name) + end + + # General purpose repetitive assertions for coercing observation queries. + # query_a is original, query_b is coerced, and query_c is coerced back. + # Returns the coerced query (query_check) for further testing + def observation_coercion_assertions(query_a, model) + query_b = query_c = [] + len = query_a.size - 1 + + [*0..len].each do |i| + # Try coercing them all. + assert(query_b[i] = query_a[i].coerce(model)) + + # They should all be new records + assert(query_b[i].record.new_record?) + assert_save(query_b[i]) + + # Check the query descriptions. + assert_equal(model.to_s, query_b[i].model.to_s) + assert_equal(:with_observations, query_b[i].flavor) + end + + # The `coerce` changes query_b, so save it for later comparison. + query_check = query_b.dup + + [*0..len].each do |i| + # Now try to coerce them back to Observation. + assert(query_c[i] = query_b[i].coerce(:Observation)) + + # They should not be new records + assert_not(query_c[i].record.new_record?) + assert_equal(query_a[i], query_c[i]) + end + + query_check + end + + def test_name_description_coercion + ds1 = name_descriptions(:coprinus_comatus_desc) + ds2 = name_descriptions(:peltigera_desc) + description_coercion_assertions(ds1, ds2, :Name) + end + + def description_coercion_assertions(ds1, ds2, model) + qa = qb = qc = [] + + desc_model = :"#{model}Description" # Several description queries can be turned into name queries and back. - q1a = Query.lookup_and_save(:NameDescription, :all) - q2a = Query.lookup_and_save(:NameDescription, :all, by_author: rolf.id) - q3a = Query.lookup_and_save(:NameDescription, :all, by_editor: rolf.id) - q4a = Query.lookup_and_save(:NameDescription, :all, by_user: rolf.id) - assert_equal(4, QueryRecord.count) + qa[0] = Query.lookup_and_save(desc_model, :all) + qa[1] = Query.lookup_and_save(desc_model, :all, by_author: rolf.id) + qa[2] = Query.lookup_and_save(desc_model, :all, by_editor: rolf.id) + qa[3] = Query.lookup_and_save(desc_model, :all, by_user: rolf.id) + qa[4] = Query.lookup_and_save(desc_model, :all, ids: [ds1.id, ds2.id]) + assert_equal(5, QueryRecord.count) # Try coercing them into name queries. - assert(q1b = q1a.coerce(:Name)) - assert(q2b = q2a.coerce(:Name)) - assert(q3b = q3a.coerce(:Name)) - assert(q4b = q4a.coerce(:Name)) - - # They should all be new records - assert(q1b.record.new_record?) - assert_save(q1b) - assert(q2b.record.new_record?) - assert_save(q2b) - assert(q3b.record.new_record?) - assert_save(q3b) - assert(q4b.record.new_record?) - assert_save(q4b) - + [*0..4].each do |i| + assert(qb[i] = qa[i].coerce(model)) + # They should all be new records + assert(qb[i].record.new_record?) + assert_save(qb[i]) + assert_equal(model.to_s, qb[i].model.to_s) + assert_equal(:with_descriptions, qb[i].flavor) + end # Make sure they're right. - assert_equal("Name", q1b.model.to_s) - assert_equal("Name", q2b.model.to_s) - assert_equal("Name", q3b.model.to_s) - assert_equal("Name", q4b.model.to_s) - assert_equal(:with_descriptions, q1b.flavor) - assert_equal(:with_descriptions, q2b.flavor) - assert_equal(:with_descriptions, q3b.flavor) - assert_equal(:with_descriptions, q4b.flavor) - assert_equal(rolf.id, q2b.params[:by_author]) - assert_equal(rolf.id, q3b.params[:by_editor]) - assert_equal(rolf.id, q4b.params[:by_user]) + assert_equal(rolf.id, qb[1].params[:by_author]) + assert_equal(rolf.id, qb[2].params[:by_editor]) + assert_equal(rolf.id, qb[3].params[:by_user]) + assert_equal([ds1.id, ds2.id], qb[4].params[:desc_ids]) # Try coercing them back. - assert(q1c = q1b.coerce(:NameDescription)) - assert(q2c = q2b.coerce(:NameDescription)) - assert(q3c = q3b.coerce(:NameDescription)) - assert(q4c = q4b.coerce(:NameDescription)) - # None should be new records - assert_equal(q1a, q1c) - assert_equal(q2a, q2c) - assert_equal(q3a, q3c) - assert_equal(q4a, q4c) + [*0..4].each do |i| + assert(qc[i] = qb[i].coerce(desc_model)) + assert_equal(qa[i], qc[i]) + end end def test_rss_log_coercion @@ -1826,10 +1643,10 @@ def test_image_with_observations_in_set images(:turned_over_image).id, images(:in_situ_image).id], :Image, :with_observations, - ids: [observations(:detailed_unknown_obs).id, - observations(:agaricus_campestris_obs).id]) + obs_ids: [observations(:detailed_unknown_obs).id, + observations(:agaricus_campestris_obs).id]) assert_query([], :Image, :with_observations, - ids: [observations(:minimal_unknown_obs).id]) + obs_ids: [observations(:minimal_unknown_obs).id]) end def test_image_with_observations_in_species_list @@ -2001,15 +1818,17 @@ def test_location_with_descriptions_by_editor end def test_location_with_descriptions_in_set - assert_query([locations(:albion), locations(:no_mushrooms_location)], - :Location, :with_descriptions, - ids: [location_descriptions(:albion_desc).id, - location_descriptions(:no_mushrooms_location_desc).id]) + assert_query( + [locations(:albion), locations(:no_mushrooms_location)], + :Location, :with_descriptions, + desc_ids: [location_descriptions(:albion_desc).id, + location_descriptions(:no_mushrooms_location_desc).id] + ) assert_query([locations(:albion)], :Location, :with_descriptions, - ids: [location_descriptions(:albion_desc).id, rolf.id]) + desc_ids: [location_descriptions(:albion_desc).id, rolf.id]) assert_query([], - :Location, :with_descriptions, ids: [rolf.id]) + :Location, :with_descriptions, desc_ids: [rolf.id]) end def test_location_with_observations @@ -2247,9 +2066,9 @@ def test_location_with_observations_for_project def test_location_with_observations_in_set assert_query([locations(:burbank).id], :Location, :with_observations, - ids: [observations(:minimal_unknown_obs).id]) + obs_ids: [observations(:minimal_unknown_obs).id]) assert_query([], :Location, :with_observations, - ids: [observations(:coprinus_comatus_obs).id]) + obs_ids: [observations(:coprinus_comatus_obs).id]) end def test_location_with_observations_in_species_list @@ -2349,6 +2168,12 @@ def test_location_description_in_set ids: [rolf.id, location_descriptions(:albion_desc).id]) end + def test_location_description_coercion + ds1 = location_descriptions(:albion_desc) + ds2 = location_descriptions(:no_mushrooms_location_desc) + description_coercion_assertions(ds1, ds2, :Location) + end + def test_name_advanced_search assert_query([names(:macrocybe_titans).id], :Name, :all, name: "macrocybe*titans") @@ -2501,7 +2326,7 @@ def test_name_with_descriptions_in_set name1 = names(:peltigera) name2 = names(:boletus_edulis) assert_query([name2, name1], - :Name, :with_descriptions, ids: [desc1, desc2, desc3]) + :Name, :with_descriptions, desc_ids: [desc1, desc2, desc3]) end def test_name_with_observations @@ -2687,9 +2512,9 @@ def test_name_with_observations_in_set names(:agaricus_campestris).id, names(:fungi).id], :Name, :with_observations, - ids: [observations(:detailed_unknown_obs).id, - observations(:agaricus_campestris_obs).id, - observations(:agaricus_campestras_obs).id]) + obs_ids: [observations(:detailed_unknown_obs).id, + observations(:agaricus_campestris_obs).id, + observations(:agaricus_campestras_obs).id]) end def test_name_with_observations_in_species_list