Methods
A
C
E
F
L
U
Instance Public methods
all(*args)

A convenience wrapper for find(:all, *args). You can pass in all the same arguments to this method as you can to find(:all).

     # File activerecord/lib/active_record/relation/finder_methods.rb, line 142
142:     def all(*args)
143:       args.any? ? apply_finder_options(args.first).to_a : to_a
144:     end
exists?(id = nil)

Returns true if a record exists in the table that matches the id or conditions given, or false otherwise. The argument can take five forms:

  • Integer - Finds the record with this primary key.
  • String - Finds the record with a primary key corresponding to this string (such as '5').
  • Array - Finds the record that matches these find-style conditions (such as ['color = ?', 'red']).
  • Hash - Finds the record that matches these find-style conditions (such as {:color => 'red'}).
  • No args - Returns false if the table is empty, true otherwise.

For more information about specifying conditions as a Hash or Array, see the Conditions section in the introduction to ActiveRecord::Base.

Note: You can’t pass in a condition as a string (like name = 'Jamie'), since it would be sanitized and then queried against the primary key column, like id = 'name = 'Jamie''.

Examples

  Person.exists?(5)
  Person.exists?('5')
  Person.exists?(:name => "David")
  Person.exists?(['name LIKE ?', "%#{query}%"])
  Person.exists?
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 171
171:     def exists?(id = nil)
172:       id = id.id if ActiveRecord::Base === id
173: 
174:       join_dependency = construct_join_dependency_for_association_find
175:       relation = construct_relation_for_association_find(join_dependency)
176:       relation = relation.except(:select).select("1").limit(1)
177: 
178:       case id
179:       when Array, Hash
180:         relation = relation.where(id)
181:       else
182:         relation = relation.where(table[primary_key.name].eq(id)) if id
183:       end
184: 
185:       connection.select_value(relation.to_sql) ? true : false
186:     end
find(*args)

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. Use Model.find(:first, *args) or its shortcut Model.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. Use Model.find(:last, *args) or its shortcut Model.last(*args).
  • Find all - This will return all the records matched by the options used. If no records are found, an empty array is returned. Use Model.find(:all, *args) or its shortcut Model.all(*args).

All approaches accept an options hash as their last parameter.

Parameters

  • :conditions - An SQL fragment like “administrator = 1”, ["user_name = ?", username], or ["user_name = :user_name", { :user_name => user_name }]. See conditions in the intro.
  • :order - An SQL fragment like “created_at DESC, name”.
  • :group - An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.
  • :having - Combined with :group this can be used to filter the records that a GROUP BY returns. Uses the HAVING SQL-clause.
  • :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.
  • :joins - Either an SQL fragment for additional joins like “LEFT JOIN comments ON comments.post_id = id” (rarely needed), named associations in the same form used for the :include option, which will perform an INNER JOIN on the associated table(s), or an array containing a mixture of both strings and named associations. If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table’s columns. Pass :readonly => false to override.
  • :include - Names associations that should be loaded alongside. The symbols named refer to already defined associations. See eager loading under Associations.
  • :select - By default, this is “*” as in “SELECT * FROM”, but can be changed if you, for example, want to do a join but not include the joined columns. Takes a string with the SELECT SQL fragment (e.g. “id, name”).
  • :from - By default, this is the table name of the class, but can be changed to an alternate table name (or even the name of a database view).
  • :readonly - Mark the returned records read-only so they cannot be saved or updated.
  • :lock - An SQL fragment like “FOR UPDATE” or “LOCK IN SHARE MODE”. :lock => true gives connection’s default exclusive lock, usually “FOR UPDATE”.

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 returned records may not be in the same order as the ids you provide since database rows are unordered. Give an explicit :order to ensure the results are sorted.

Examples

  # find first
  Person.first # returns the first object fetched by SELECT * FROM people
  Person.where(["user_name = ?", user_name]).first
  Person.where(["user_name = :u", { :u => user_name }]).first
  Person.order("created_on DESC").offset(5).first

  # find last
  Person.last # returns the last object fetched by SELECT * FROM people
  Person.where(["user_name = ?", user_name]).last
  Person.order("created_on DESC").offset(5).last

  # find all
  Person.all # returns an array of objects for all the rows fetched by SELECT * FROM people
  Person.where(["category IN (?)", categories]).limit(50).all
  Person.where({ :friends => ["Bob", "Steve", "Fred"] }).all
  Person.offset(10).limit(10).all
  Person.includes([:account, :friends]).all
  Person.group("category").all

Example for find with a lock: Imagine two concurrent transactions: each will read person.visits == 2, add 1 to it, and save, resulting in two saves of person.visits = 3. By locking the row, the second transaction has to wait until the first is finished; we get the expected person.visits == 4.

  Person.transaction do
    person = Person.lock(true).find(1)
    person.visits += 1
    person.save!
  end
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 95
 95:     def find(*args)
 96:       return to_a.find { |*block_args| yield(*block_args) } if block_given?
 97: 
 98:       options = args.extract_options!
 99: 
100:       if options.present?
101:         apply_finder_options(options).find(*args)
102:       else
103:         case args.first
104:         when :first, :last, :all
105:           send(args.first)
106:         else
107:           find_with_ids(*args)
108:         end
109:       end
110:     end
first(*args)

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 activerecord/lib/active_record/relation/finder_methods.rb, line 114
114:     def first(*args)
115:       if args.any?
116:         if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
117:           to_a.first(*args)
118:         else
119:           apply_finder_options(args.first).first
120:         end
121:       else
122:         find_first
123:       end
124:     end
last(*args)

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 activerecord/lib/active_record/relation/finder_methods.rb, line 128
128:     def last(*args)
129:       if args.any?
130:         if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
131:           to_a.last(*args)
132:         else
133:           apply_finder_options(args.first).last
134:         end
135:       else
136:         find_last
137:       end
138:     end
Instance Protected methods
apply_join_dependency(relation, join_dependency)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 215
215:     def apply_join_dependency(relation, join_dependency)
216:       for association in join_dependency.join_associations
217:         relation = association.join_relation(relation)
218:       end
219: 
220:       limitable_reflections = using_limitable_reflections?(join_dependency.reflections)
221: 
222:       if !limitable_reflections && relation.limit_value
223:         limited_id_condition = construct_limited_ids_condition(relation.except(:select))
224:         relation = relation.where(limited_id_condition)
225:       end
226: 
227:       relation = relation.except(:limit, :offset) unless limitable_reflections
228: 
229:       relation
230:     end
column_aliases(join_dependency)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 353
353:     def column_aliases(join_dependency)
354:       join_dependency.joins.collect{|join| join.column_names_with_alias.collect{|column_name, aliased_name|
355:           "#{connection.quote_table_name join.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}"}}.flatten.join(", ")
356:     end
construct_join_dependency_for_association_find()
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 198
198:     def construct_join_dependency_for_association_find
199:       including = (@eager_load_values + @includes_values).uniq
200:       join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, nil)
201:     end
construct_limited_ids_condition(relation)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 232
232:     def construct_limited_ids_condition(relation)
233:       orders = relation.order_values.join(", ")
234:       values = @klass.connection.distinct("#{@klass.connection.quote_table_name @klass.table_name}.#{@klass.primary_key}", orders)
235: 
236:       ids_array = relation.select(values).collect {|row| row[@klass.primary_key]}
237:       ids_array.empty? ? raise(ThrowResult) : primary_key.in(ids_array)
238:     end
construct_relation_for_association_calculations()
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 203
203:     def construct_relation_for_association_calculations
204:       including = (@eager_load_values + @includes_values).uniq
205:       join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, arel.join_sql)
206:       relation = except(:includes, :eager_load, :preload)
207:       apply_join_dependency(relation, join_dependency)
208:     end
construct_relation_for_association_find(join_dependency)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 210
210:     def construct_relation_for_association_find(join_dependency)
211:       relation = except(:includes, :eager_load, :preload, :select).select(column_aliases(join_dependency))
212:       apply_join_dependency(relation, join_dependency)
213:     end
find_by_attributes(match, attributes, *args)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 240
240:     def find_by_attributes(match, attributes, *args)
241:       conditions = Hash[attributes.map {|a| [a, args[attributes.index(a)]]}]
242:       result = where(conditions).send(match.finder)
243: 
244:       if match.bang? && result.blank?
245:         raise RecordNotFound, "Couldn't find #{@klass.name} with #{conditions.to_a.collect {|p| p.join(' = ')}.join(', ')}"
246:       else
247:         result
248:       end
249:     end
find_first()
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 337
337:     def find_first
338:       if loaded?
339:         @records.first
340:       else
341:         @first ||= limit(1).to_a[0]
342:       end
343:     end
find_last()
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 345
345:     def find_last
346:       if loaded?
347:         @records.last
348:       else
349:         @last ||= reverse_order.limit(1).to_a[0]
350:       end
351:     end
find_one(id)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 296
296:     def find_one(id)
297:       id = id.id if ActiveRecord::Base === id
298: 
299:       record = where(primary_key.eq(id)).first
300: 
301:       unless record
302:         conditions = arel.where_sql
303:         conditions = " [#{conditions}]" if conditions
304:         raise RecordNotFound, "Couldn't find #{@klass.name} with ID=#{id}#{conditions}"
305:       end
306: 
307:       record
308:     end
find_or_instantiator_by_attributes(match, attributes, *args)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 251
251:     def find_or_instantiator_by_attributes(match, attributes, *args)
252:       protected_attributes_for_create, unprotected_attributes_for_create = {}, {}
253:       args.each_with_index do |arg, i|
254:         if arg.is_a?(Hash)
255:           protected_attributes_for_create = args[i].with_indifferent_access
256:         else
257:           unprotected_attributes_for_create[attributes[i]] = args[i]
258:         end
259:       end
260: 
261:       conditions = (protected_attributes_for_create.merge(unprotected_attributes_for_create)).slice(*attributes).symbolize_keys
262: 
263:       record = where(conditions).first
264: 
265:       unless record
266:         record = @klass.new do |r|
267:           r.send(:attributes=, protected_attributes_for_create, true) unless protected_attributes_for_create.empty?
268:           r.send(:attributes=, unprotected_attributes_for_create, false) unless unprotected_attributes_for_create.empty?
269:         end
270:         yield(record) if block_given?
271:         record.save if match.instantiator == :create
272:       end
273: 
274:       record
275:     end
find_some(ids)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 310
310:     def find_some(ids)
311:       result = where(primary_key.in(ids)).all
312: 
313:       expected_size =
314:         if @limit_value && ids.size > @limit_value
315:           @limit_value
316:         else
317:           ids.size
318:         end
319: 
320:       # 11 ids with limit 3, offset 9 should give 2 results.
321:       if @offset_value && (ids.size - @offset_value < expected_size)
322:         expected_size = ids.size - @offset_value
323:       end
324: 
325:       if result.size == expected_size
326:         result
327:       else
328:         conditions = arel.wheres.map { |x| x.value }.join(', ')
329:         conditions = " [WHERE #{conditions}]" if conditions.present?
330: 
331:         error = "Couldn't find all #{@klass.name.pluralize} with IDs "
332:         error << "(#{ids.join(", ")})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
333:         raise RecordNotFound, error
334:       end
335:     end
find_with_associations()
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 190
190:     def find_with_associations
191:       join_dependency = construct_join_dependency_for_association_find
192:       rows = construct_relation_for_association_find(join_dependency).to_a
193:       join_dependency.instantiate(rows)
194:     rescue ThrowResult
195:       []
196:     end
find_with_ids(*ids)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 277
277:     def find_with_ids(*ids)
278:       return to_a.find { |*block_args| yield(*block_args) } if block_given?
279: 
280:       expects_array = ids.first.kind_of?(Array)
281:       return ids.first if expects_array && ids.first.empty?
282: 
283:       ids = ids.flatten.compact.uniq
284: 
285:       case ids.size
286:       when 0
287:         raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
288:       when 1
289:         result = find_one(ids.first)
290:         expects_array ? [ result ] : result
291:       else
292:         find_some(ids)
293:       end
294:     end
using_limitable_reflections?(reflections)
     # File activerecord/lib/active_record/relation/finder_methods.rb, line 358
358:     def using_limitable_reflections?(reflections)
359:       reflections.none? { |r| r.collection? }
360:     end