lib/neo4j/active_node/labels.rb in neo4j-3.0.0.alpha.7 vs lib/neo4j/active_node/labels.rb in neo4j-3.0.0.alpha.8

- old
+ new

@@ -6,10 +6,11 @@ module Labels extend ActiveSupport::Concern WRAPPED_CLASSES = [] class InvalidQueryError < StandardError; end + class RecordNotFound < StandardError; end # @return the labels # @see Neo4j-core def labels @_persisted_node.labels @@ -57,42 +58,50 @@ end end module ClassMethods - # Find all nodes/objects of this class, with given search criteria - # @param [Hash, nil] args the search critera or nil if finding all - # @param [Neo4j::Session] session defaults to the model's session - def all(args = nil, session = self.neo4j_session) - if args - find_by_hash(args, session) - else - Neo4j::Label.find_all_nodes(mapped_label_name, session) - end + # Find all nodes/objects of this class + def all + self.query_as(:n).pluck(:n) end + def first + self.query_as(:n).limit(1).order('n.neo_id').pluck(:n).first + end + + def last + count = self.count + final_count = count == 0 ? 0 : count - 1 + self.query_as(:n).order('n.neo_id').skip(final_count).limit(1).pluck(:n).first + end + # @return [Fixnum] number of nodes of this class - def count(session = self.neo4j_session) - q = session.query(label: mapped_label_name, return: "count(n) AS count", map_return: :value) - q.to_a[0] + def count + self.query_as(:n).return("count(n) AS count").first.count end - # Same as #all but return only one object - # If given a String or Fixnum it will return the object with that neo4j id. - # @param [Hash,String,Fixnum] args search criteria - def find(args, session = self.neo4j_session) - case args - when Hash - find_by_hash(args, session).first - when String, Fixnum - Neo4j::Node.load(args.to_i) - else - raise "Unknown argument #{args.class} in find method" - end + # Returns the object with the specified neo4j id. + # @param [String,Fixnum] neo_id of node to find + def find(id) + raise "Unknown argument #{id.class} in find method" if not [String, Fixnum].include?(id.class) + + Neo4j::Node.load(id.to_i) end + # Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself. + # @param [Hash] hash of arguments to find + def find_by(*args) + self.query_as(:n).where(n: eval(args.join)).limit(1).pluck(:n).first + end + # Like find_by, except that if no record is found, raises a RecordNotFound error. + def find_by!(*args) + a = eval(args.join) + find_by(args) or raise RecordNotFound, "#{self.query_as(:n).where(n: a).limit(1).to_cypher} returned no results" + end + # Destroy all nodes an connected relationships def destroy_all self.neo4j_session._query("MATCH (n:`#{mapped_label_name}`)-[r]-() DELETE n,r") self.neo4j_session._query("MATCH (n:`#{mapped_label_name}`) DELETE n") end @@ -126,57 +135,9 @@ def indexed_labels end protected - - def find_by_hash(query, session) - validate_query!(query) - - extract_relationship_conditions!(query) - - session.query(query.merge(label: mapped_label_name)) - end - - # Raises an error if query is malformed - def validate_query!(query) - invalid_query_keys = query.keys.map(&:to_sym) - [:conditions, :order, :limit, :skip] - - raise InvalidQueryError, "Invalid query keys: #{invalid_query_keys.join(', ')}" if not invalid_query_keys.empty? - end - - # Takes out :conditions query keys for associations and creates corresponding :conditions and :match keys - # example: - # class Person - # property :name - # has_n :friend - # end - # - # :conditions => {name: 'Fred', friend: person} - # should result in: - # :conditions => {name => 'Fred', 'id(n1)' => person.id}, :match => 'n--n1' - # - def extract_relationship_conditions!(query) - node_num = 1 - if query[:conditions] - query[:conditions].dup.each do |key, value| - if has_one_relationship?(key) - neo_id = value.try(:neo_id) || value - raise InvalidQueryError, "Invalid value for '#{key}' condition" if not neo_id.is_a?(Integer) - - query[:match] ||= [] - n_string = "n#{node_num}" - dir = relationship_dir(key) - - match = dir == :outgoing ? "n-->(#{n_string})" : "n<--(#{n_string})" - query[:match] << match - query[:conditions]["id(#{n_string})"] = neo_id.to_i - query[:conditions].delete(key) - node_num += 1 - end - end - end - end def _index(property) mapped_labels.each do |label| # make sure the property is not indexed twice existing = label.indexes[:property_keys]