module DatastaxRails::FinderMethods
Relation
methods to locate a single record either by PK or set of values.
Public Instance Methods
Find operates with four different retrieval approaches:
-
Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). If no record can be found for all of the listed ids, then
RecordNotFound
will be raised. -
Find first - This will return the first record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched,
nil
is returned. UseModel.find(:first, *args)
or its shortcutModel.first(*args)
. -
Find last - This will return the last record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched,
nil
is returned. UseModel.find(:last, *args)
or its shortcutModel.last(*args)
.
All approaches accept an options hash as their last parameter.
Options¶ ↑
-
:conditions
- See conditions in the intro. -
:order
- An SQL fragment like “created_at DESC, name”. -
:limit
- An integer determining the limit on the number of rows that should be returned. -
:offset
- An integer determining the offset from where the rows should be fetched. So at 5, it would skip rows 0 through 4.
Examples¶ ↑
# find by id
Person.find(1) # returns the object for ID = 1 Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6) Person.find([7, 17]) # returns an array for objects with IDs in (7, 17) Person.find([1]) # returns an array for the object with ID = 1 Person.where(:administrator => 1).order(:created_on => :desc).find(1)
Note that the returned order is undefined unless you give a specific :order
clause. Further note that order is handled in memory and so does suffer a performance penalty.
Examples¶ ↑
# find first Person.first # returns the first object fetched by SELECT * FROM people Person.where(:user_name => user_name).first Person.order(:created_on => :desc).offset(5).first # find last Person.last # returns the last object in the column family Person.where(:user_name => user_name).last Person.order(:created_at => :desc).offset(5).last
# File lib/datastax_rails/relation/finder_methods.rb, line 48 def find(*args) return to_a.find { |*block_args| yield(*block_args) } if block_given? options = args.extract_options! if options.present? apply_finder_options(options).find(*args) else case args.first when :first, :last send(args.first) else self.use_solr_value = false find_with_ids(*args) end end end
Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself.
If no record is found, returns nil
.
Post.find_by name: 'Spartacus', rating: 4 Post.find_by “published_at < ?”, 2.weeks.ago
# File lib/datastax_rails/relation/finder_methods.rb, line 73 def find_by(*args) where_values << escape_attributes(args.first) dont_escape.first end
Like find_by
, except that if no record is found, raises an DatastaxRails::RecordNotFound
error.
# File lib/datastax_rails/relation/finder_methods.rb, line 80 def find_by!(*args) where_values << escape_attributes(args.first) dont_escape.first! end
A convenience wrapper for find(:first, *args)
. You can pass in all the same arguments to this method as you can to find(:first)
.
# File lib/datastax_rails/relation/finder_methods.rb, line 87 def first(*args) if args.any? if args.first.is_a?(Integer) || (loaded? && !args.first.is_a?(Hash)) limit(*args).to_a else apply_finder_options(args.first).first end else find_first end end
Same as first
but raises DatastaxRails::RecordNotFound
if no record is found. Note that first!
accepts no arguments.
# File lib/datastax_rails/relation/finder_methods.rb, line 101 def first! first || fail(RecordNotFound) end
A convenience wrapper for find(:last, *args)
. You can pass in all the same arguments to this method as you can to find(:last)
.
# File lib/datastax_rails/relation/finder_methods.rb, line 107 def last(*args) if args.any? if args.first.is_a?(Integer) || (loaded? && !args.first.is_a?(Hash)) if order_values.empty? && reorder_value.nil? order(id: :desc).limit(*args).reverse else to_a.last(*args) end else apply_finder_options(args.first).last end else find_last end end
Same as last
but raises DatastaxRails::RecordNotFound
if no record is found. Note that last!
accepts no arguments.
# File lib/datastax_rails/relation/finder_methods.rb, line 125 def last! last || fail(RecordNotFound) end
Private Instance Methods
# File lib/datastax_rails/relation/finder_methods.rb, line 145 def escape_attributes(conditions) escaped = {} conditions.each do |k, v| if v.is_a?(String) escaped[k] = v.gsub(/([^\w\- ])/, '\\\\\1') else escaped[k] = v end end escaped end
# File lib/datastax_rails/relation/finder_methods.rb, line 212 def find_first if loaded? @results.first else @first ||= limit(1).to_a[0] end end
# File lib/datastax_rails/relation/finder_methods.rb, line 220 def find_last if loaded? @results.last else @last ||= reverse_order.limit(1).to_a[0] end end
# File lib/datastax_rails/relation/finder_methods.rb, line 176 def find_one(id) key = @klass.attribute_definitions[@klass.primary_key].type_cast_for_cql3(id) key || fail(RecordNotFound, "Couldn't find #{@klass.name} with an invalid ID=#{id}") with_cassandra.where(@klass.primary_key => key).first || fail(RecordNotFound, "Couldn't find #{@klass.name} with ID=#{id}") end
# File lib/datastax_rails/relation/finder_methods.rb, line 184 def find_some(ids) keys = ids.map do |id| @klass.attribute_definitions[@klass.primary_key].type_cast_for_cql3(id) || fail(RecordNotFound, "Couldn't find #{@klass.name} with an invalid ID=#{id}") end result = with_cassandra.where(@klass.primary_key => keys).all expected_size = if @limit_value && ids.size > @limit_value @limit_value else ids.size end # 11 ids with limit 3, offset 9 should give 2 results. if @offset_value && (ids.size - @offset_value < expected_size) expected_size = ids.size - @offset_value end if result.size == expected_size result else error = "Couldn't find all #{@klass.name.pluralize} with IDs " error << "(#{ids.join(', ')}) (found #{result.size} results, but was looking for #{expected_size})" fail RecordNotFound, error end end
# File lib/datastax_rails/relation/finder_methods.rb, line 157 def find_with_ids(*ids) return to_a.find { |*block_args| yield(*block_args) } if block_given? expects_array = ids.first.is_a?(Array) return ids.first if expects_array && ids.first.empty? ids = ids.flatten.compact.uniq case ids.size when 0 fail RecordNotFound, "Couldn't find #{@klass.name} without an ID" when 1 result = find_one(ids.first) expects_array ? [result] : result else find_some(ids) end end