QutBioacousticsResearchGroup/bioacoustic-workbench

View on GitHub
app/models/saved_search/saved_search_store.rb

Summary

Maintainability
C
1 day
Test Coverage
class SavedSearchStore
  #http://edgeguides.rubyonrails.org/active_model_basics.html#validations
  include ActiveModel::Validations

  # example:
  # test = Search.new( { :pre => { :created_by_id => 1 }, :body => { :project_ids => [1,2,3,4] } } )

  # does not store/cache results. Should it?

  attr_accessor :pre_params, :body_params, :post_params

  def initialize(args)
    args.each do |k, v|
      instance_variable_set("@#{k}", v) unless v.nil?
    end
  end

  validate :params_are_hashes

  def params_are_hashes
    self.pre_params = SavedSearchStorePre.new(self.pre_params) if self.pre_params.is_a?(Hash)
    self.body_params = SavedSearchStoreBody.new(self.body_params) if self.body_params.is_a?(Hash)
    self.post_params = SavedSearchStorePost.new(self.post_params) if self.post_params.is_a?(Hash)

    self.errors.add(:pre_params, "must be a SavedSearchPre, given #{self.pre_params.class} with value #{self.pre_params}.") unless self.pre_params.is_a?(SavedSearchStorePre) || self.pre_params.blank?
    self.errors.add(:body_params, "must be a SavedSearchBody, given #{self.body_params.class} with value #{self.body_params}.") unless self.body_params.is_a?(SavedSearchStoreBody) || self.body_params.blank?
    self.errors.add(:post_params, "must be a SavedSearchPost, given #{self.post_params.class} with value #{self.post_params}.") unless self.post_params.is_a?(SavedSearchStorePost) || self.post_params.blank?
  end

  # create query with deterministic ordering
  def create_query
    create_raw_query.select('audio_recordings.id, audio_recordings.uuid').order('audio_recordings.recorded_date')
  end

  # create a query using the state of this Search instance.
  def create_raw_query

    recordings_search = AudioRecording.scoped

    if self.invalid?
      raise ArgumentError, "SavedSearchStore has errors: #{self.errors.to_json}."
    end

    unless self.pre_params.blank?
      if self.pre_params.invalid?
        raise ArgumentError, "SavedSearchStorePre has errors: #{self.pre_params.errors.to_json}."
      end
    end

    unless self.body_params.blank?

      if self.body_params.invalid?
        raise ArgumentError, "SavedSearchStoreBody has errors: #{self.body_params.errors.to_json}."
      end

      # these are in a specific order, from the ones that will filter the most, to those that will filter the least.
      recordings_search = recordings_search.recording_ids(self.body_params.audio_recording_id) if self.body_params.audio_recording_id
      recordings_search = recordings_search.recording_uuids(self.body_params.audio_recording_uuid) if self.body_params.audio_recording_uuid

      recordings_search = recordings_search.recording_projects(self.body_params.project_id) if  self.body_params.project_id
      recordings_search = recordings_search.recording_sites(self.body_params.site_id) if  self.body_params.site_id

      if  self.body_params.date_start && self.body_params.date_end
        recordings_search = recordings_search.recording_within_date(self.body_params.date_start, self.body_params.date_end)
      elsif self.body_params.date_start
        recordings_search = recordings_search.recording_within_date(self.body_params.date_start, self.body_params.date_start)
      elsif self.body_params.date_end
        recordings_search = recordings_search.recording_within_date(self.body_params.date_end, self.body_params.date_end)
      end

      if self.body_params.time_start && self.body_params.time_end
        recordings_search = recordings_search.recording_within_time(self.body_params.time_start, self.body_params.time_end)
      elsif self.body_params.time_start
        recordings_search = recordings_search.recording_within_time(self.body_params.time_start, self.body_params.time_start)
      elsif self.body_params.time_end
        recordings_search = recordings_search.recording_within_time(self.body_params.time_end, self.body_params.time_end)
      end

      recordings_search = recordings_search.recording_tags(self.body_params.tags) if self.body_params.tags
    end


    unless self.post_params.blank?
      if self.post_params.invalid?
        raise ArgumentError, "SavedSearchStorePost has errors: #{self.post_params.errors}."
      end
    end

    recordings_search
  end

  # execute a query to get the dataset
  def execute_query
    the_query = create_query

    #to do: start and end offsets
    results = the_query.all.collect { |result|
      the_result = {id: result.id, uuid: result.uuid, start_offset_seconds: nil, end_offset_seconds: nil}
      OpenStruct.new(the_result)
    }
    to_return = {:search => self, :query => the_query, :items => results}
    OpenStruct.new(to_return)
  end

  def to_s
    self.to_json
  end
end