module ActiveFedora::FinderMethods

def build_query(conditions)

def build_query(conditions)
  clauses = search_model_clause ?  [search_model_clause] : []
  clauses += conditions.reject{|c| c.blank?}
  return "*:*" if clauses.empty?
  clauses.compact.join(" AND ")
end

def class_to_load(resource, cast)

def class_to_load(resource, cast)
  if @klass == ActiveFedora::Base && cast == false
    ActiveFedora::Base
  else
    # The true class may be a subclass of @klass, so always use from_class_uri
    resource_class = Model.from_class_uri(has_model_value(resource)) || ActiveFedora::Base
    unless equivalent_class?(resource_class)
      raise ActiveFedora::ActiveFedoraError.new("Model mismatch. Expected #{@klass}. Got: #{resource_class}") 
    end
    resource_class
  end
end

def condition_to_clauses(key, value)

def condition_to_clauses(key, value)
  unless value.nil?
    # if the key is a property name, turn it into a solr field
    if @klass.delegated_attributes.key?(key)
      # TODO Check to see if `key' is a possible solr field for this class, if it isn't try :searchable instead
      key = ActiveFedora::SolrQueryBuilder.solr_name(key, :stored_searchable, type: :string)
    end
    if value.empty?
      "-#{key}:['' TO *]"
    elsif value.is_a? Array
      value.map { |val| "#{key}:#{solr_escape(val)}" }
    else
      key = SOLR_DOCUMENT_ID if (key === :id || key === :id)
      "#{key}:#{solr_escape(value)}"
    end
  end
end

def create_query(conditions)

@param[Hash] conditions solr conditions to match
Returns a solr query for the supplied conditions
def create_query(conditions)
    case conditions
    when Hash
      build_query([create_query_from_hash(conditions)])
    when String
      build_query(["(#{conditions})"])
    else
      build_query(conditions)
    end
end

def create_query_from_hash(conditions)

def create_query_from_hash(conditions)
  conditions.map {|key,value| condition_to_clauses(key, value)}.compact.join(" AND ")
end

def equivalent_class?(other_class)

def equivalent_class?(other_class)
  other_class <= @klass
end

def exists?(conditions)

@return[boolean]
@param[ActiveFedora::Base, String, Hash] object, id or hash of conditions
Returns false if param is false (or nil)
Returns true if object having the id or matching the conditions exists in the repository
def exists?(conditions)
  conditions = conditions.id if Base === conditions
  return false if !conditions
  case conditions
  when Hash
    find_with_conditions(conditions, {rows: 1}).present?
  when String
    !!find(conditions)
  else
    raise ArgumentError, "`conditions' argument must be ActiveFedora::Base, String, or Hash: #{conditions.inspect}"
  end
rescue ActiveFedora::ObjectNotFoundError, Ldp::Gone
  false
end

def find(*args)

Options Hash: (**args)
  • :cast (Boolean) -- when true, examine the model and cast it to the first known cModel
  • :rows (Integer) -- when :all is passed, the maximum number of rows to load from solr
def find(*args)
  return to_a.find { |*block_args| yield(*block_args) } if block_given?
  options = args.extract_options!
  options = options.dup
  cast = if @klass == ActiveFedora::Base && !options.has_key?(:cast)
    true
  else
    options.delete(:cast)
  end
  if options[:sort]
    # Deprecate sort sometime?
    sort = options.delete(:sort)
    options[:order] ||= sort if sort.present?
  end
  if options.present?
    options = args.first unless args.empty?
    Deprecation.warn(ActiveFedora::Base, "Calling .find with a hash has been deprecated and will not be allowed in active-fedora 10.0. Use .where instead")
    options = {conditions: options}
    apply_finder_options(options)
  else
    raise ArgumentError, "#{self}.find() expects an id. You provided `#{args.inspect}'" unless args.is_a? Array
    find_with_ids(args, cast)
  end
end

def find_each( conditions={}, opts={})

Options Hash: (**opts)
  • :cast (Boolean) -- when true, examine the model and cast it to the first known cModel

Parameters:
  • opts (Hash) --
  • conditions (Hash) -- the conditions for the solr search to match
def find_each( conditions={}, opts={})
  cast = opts.delete(:cast)
  find_in_batches(conditions, opts.merge({:fl=>SOLR_DOCUMENT_ID})) do |group|
    group.each do |hit|
      begin
        yield(load_from_fedora(hit[SOLR_DOCUMENT_ID], cast))
      rescue Ldp::Gone
        ActiveFedora::Base.logger.error "Although #{hit[SOLR_DOCUMENT_ID]} was found in Solr, it doesn't seem to exist in Fedora. The index is out of synch." if ActiveFedora::Base.logger
      end
    end
  end
end

def find_in_batches conditions, opts={}

def find_in_batches conditions, opts={}
  opts[:q] = create_query(conditions)
  opts[:qt] = @klass.solr_query_handler
  #set default sort to created date ascending
  unless opts[:sort].present?
    opts[:sort]= @klass.default_sort_params
  end
  batch_size = opts.delete(:batch_size) || 1000
  counter = 0
  begin
    counter += 1
    response = ActiveFedora::SolrService.instance.conn.paginate counter, batch_size, "select", :params => opts
    docs = response["response"]["docs"]
    yield docs
  end while docs.has_next?
end

def find_one(id, cast=nil)

Other tags:
    Example: because the object hydra:dataset1 asserts it is a Dataset (hasModel http://fedora.info/definitions/v4/model#Dataset), return a Dataset object (not a Book). -

Parameters:
  • cast (Boolean) -- when true, cast the found object to the class of the first known model defined in it's RELS-EXT
  • id (String) -- of the object to load
def find_one(id, cast=nil)
  if where_values.empty?
    load_from_fedora(id, cast)
  else
    conditions = where_values + [ActiveFedora::SolrQueryBuilder.raw_query(SOLR_DOCUMENT_ID, id)]
    query = conditions.join(" AND ".freeze)
    to_enum(:find_each, query, {}).to_a.first
  end
end

def find_some(ids, cast)

def find_some(ids, cast)
  ids.map{|id| find_one(id, cast)}
end

def find_take

def find_take
  if loaded?
    @records.first
  else
    @take ||= limit(1).to_a.first
  end
end

def find_with_conditions(conditions, opts={})

Options Hash: (**opts)
  • :rows (Array) -- number of rows to return
  • :sort (Array) -- a list of fields to sort by
def find_with_conditions(conditions, opts={})
  #set default sort to created date ascending
  unless opts.include?(:sort)
    opts[:sort]=@klass.default_sort_params
  end
  SolrService.query(create_query(conditions), opts) 
end

def find_with_ids(ids, cast)

def find_with_ids(ids, cast)
  expects_array = ids.first.kind_of?(Array)
  return ids.first if expects_array && ids.first.empty?
  ids = ids.flatten.compact.uniq
  case ids.size
  when 0
    raise ArgumentError, "Couldn't find #{@klass.name} without an ID"
  when 1
    result = find_one(ids.first, cast)
    expects_array ? [ result ] : result
  else
    find_some(ids, cast)
  end
end

def first

=> #
Person.where(name_t: 'Jones').first
@example

Returns the first records that was found.
def first
  if loaded?
    @records.first
  else
    @first ||= limit(1).to_a[0]
  end
end

def has_model_value(resource)

def has_model_value(resource)
  best_model_match = nil
  resource.graph.query([nil, ActiveFedora::RDF::Fcrepo::Model.hasModel, nil]).each do |rg|
    model_value = Model.from_class_uri(rg.object.to_s)
    if model_value
      best_model_match ||= model_value
      # If there is an inheritance structure, use the most specific case.
      if best_model_match > model_value
        best_model_match = model_value
      end
    end
  end
  best_model_match.to_s
end

def last

=> #
Person.where(name_t: 'Jones').last
@example

how ActiveRecord would achieve the same behavior.
Returns the last record sorted by id. ID was chosen because this mimics
def last
  if loaded?
    @records.last
  else
    @last ||= order('id desc').limit(1).to_a[0]
  end
end

def load_from_fedora(id, cast)

def load_from_fedora(id, cast)
  raise ActiveFedora::ObjectNotFoundError if id.empty?
  resource = ActiveFedora.fedora.ldp_resource_service.build(klass, id)
  raise ActiveFedora::ObjectNotFoundError if resource.new?
  class_to_load(resource, cast).allocate.init_with_resource(resource) # Triggers the find callback
end

def search_model_clause

Return the solr clause that queries for this type of class
def search_model_clause
  # The concrete class could could be any subclass of @klass or @klass itself
  unless @klass == ActiveFedora::Base
    clauses = ([@klass] + @klass.descendants).map do |k|
      ActiveFedora::SolrQueryBuilder.construct_query_for_rel(has_model: k.to_s)
    end
    clauses.size == 1 ? clauses.first : "(#{clauses.join(" OR ")})"
  end
end

def solr_escape terms

See rsolr/rsolr#101
Adds esaping for spaces which are not handled by RSolr.solr_escape
def solr_escape terms
  RSolr.solr_escape(terms).gsub(/\s+/,"\\ ")
end

def take(limit = nil)

Person.where(["name LIKE '%?'", name]).take
Person.take(5) # returns 5 objects fetched by SELECT * FROM people LIMIT 5
Person.take # returns an object fetched by SELECT * FROM people LIMIT 1

If an order is supplied it will be respected.
order. The order will depend on the database implementation.
Gives a record (or N records if a parameter is supplied) without any implied
def take(limit = nil)
  limit ? limit(limit).to_a : find_take
end