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 lib/active_record/relation/finder_methods.rb, line 158 158: def all(*args) 159: args.any? ? apply_finder_options(args.first).to_a : to_a 160: end
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''.
Person.exists?(5) Person.exists?('5') Person.exists?(:name => "David") Person.exists?(['name LIKE ?', "%#{query}%"]) Person.exists?
# File lib/active_record/relation/finder_methods.rb, line 187 187: def exists?(id = false) 188: id = id.id if ActiveRecord::Base === id 189: return false if id.nil? 190: 191: join_dependency = construct_join_dependency_for_association_find 192: relation = construct_relation_for_association_find(join_dependency) 193: relation = relation.except(:select, :order).select("1 AS one").limit(1) 194: 195: case id 196: when Array, Hash 197: relation = relation.where(id) 198: else 199: relation = relation.where(table[primary_key].eq(id)) if id 200: end 201: 202: connection.select_value(relation, "#{name} Exists") ? true : false 203: rescue ThrowResult 204: false 205: end
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.
: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”.
# 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.
# 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 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
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/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: limit(*args).to_a 118: else 119: apply_finder_options(args.first).first 120: end 121: else 122: find_first 123: end 124: end
Same as first but raises ActiveRecord::RecordNotFound if no record is found. Note that first! accepts no arguments.
# File lib/active_record/relation/finder_methods.rb, line 128 128: def first! 129: first or raise RecordNotFound 130: 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/active_record/relation/finder_methods.rb, line 134 134: def last(*args) 135: if args.any? 136: if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash)) 137: if order_values.empty? 138: order("#{primary_key} DESC").limit(*args).reverse 139: else 140: to_a.last(*args) 141: end 142: else 143: apply_finder_options(args.first).last 144: end 145: else 146: find_last 147: end 148: end
# File lib/active_record/relation/finder_methods.rb, line 235 235: def apply_join_dependency(relation, join_dependency) 236: join_dependency.join_associations.each do |association| 237: relation = association.join_relation(relation) 238: end 239: 240: limitable_reflections = using_limitable_reflections?(join_dependency.reflections) 241: 242: if !limitable_reflections && relation.limit_value 243: limited_id_condition = construct_limited_ids_condition(relation.except(:select)) 244: relation = relation.where(limited_id_condition) 245: end 246: 247: relation = relation.except(:limit, :offset) unless limitable_reflections 248: 249: relation 250: end
# File lib/active_record/relation/finder_methods.rb, line 218 218: def construct_join_dependency_for_association_find 219: including = (@eager_load_values + @includes_values).uniq 220: ActiveRecord::Associations::JoinDependency.new(@klass, including, []) 221: end
# File lib/active_record/relation/finder_methods.rb, line 252 252: def construct_limited_ids_condition(relation) 253: orders = relation.order_values.map { |val| val.presence }.compact 254: values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) 255: 256: relation = relation.dup 257: 258: ids_array = relation.select(values).collect {|row| row[primary_key]} 259: ids_array.empty? ? raise(ThrowResult) : table[primary_key].in(ids_array) 260: end
# File lib/active_record/relation/finder_methods.rb, line 223 223: def construct_relation_for_association_calculations 224: including = (@eager_load_values + @includes_values).uniq 225: join_dependency = ActiveRecord::Associations::JoinDependency.new(@klass, including, arel.froms.first) 226: relation = except(:includes, :eager_load, :preload) 227: apply_join_dependency(relation, join_dependency) 228: end
# File lib/active_record/relation/finder_methods.rb, line 230 230: def construct_relation_for_association_find(join_dependency) 231: relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns) 232: apply_join_dependency(relation, join_dependency) 233: end
# File lib/active_record/relation/finder_methods.rb, line 262 262: def find_by_attributes(match, attributes, *args) 263: conditions = Hash[attributes.map {|a| [a, args[attributes.index(a)]]}] 264: result = where(conditions).send(match.finder) 265: 266: if match.bang? && result.blank? 267: raise RecordNotFound, "Couldn't find #{@klass.name} with #{conditions.to_a.collect {|p| p.join(' = ')}.join(', ')}" 268: else 269: yield(result) if block_given? 270: result 271: end 272: end
# File lib/active_record/relation/finder_methods.rb, line 374 374: def find_first 375: if loaded? 376: @records.first 377: else 378: @first ||= limit(1).to_a[0] 379: end 380: end
# File lib/active_record/relation/finder_methods.rb, line 382 382: def find_last 383: if loaded? 384: @records.last 385: else 386: @last ||= 387: if offset_value || limit_value 388: to_a.last 389: else 390: reverse_order.limit(1).to_a[0] 391: end 392: end 393: end
# File lib/active_record/relation/finder_methods.rb, line 319 319: def find_one(id) 320: id = id.id if ActiveRecord::Base === id 321: 322: if IdentityMap.enabled? && where_values.blank? && 323: limit_value.blank? && order_values.blank? && 324: includes_values.blank? && preload_values.blank? && 325: readonly_value.nil? && joins_values.blank? && 326: !@klass.locking_enabled? && 327: record = IdentityMap.get(@klass, id) 328: return record 329: end 330: 331: column = columns_hash[primary_key] 332: 333: substitute = connection.substitute_at(column, @bind_values.length) 334: relation = where(table[primary_key].eq(substitute)) 335: relation.bind_values = [[column, id]] 336: record = relation.first 337: 338: unless record 339: conditions = arel.where_sql 340: conditions = " [#{conditions}]" if conditions 341: raise RecordNotFound, "Couldn't find #{@klass.name} with #{primary_key}=#{id}#{conditions}" 342: end 343: 344: record 345: end
# File lib/active_record/relation/finder_methods.rb, line 274 274: def find_or_instantiator_by_attributes(match, attributes, *args) 275: options = args.size > 1 && args.last(2).all?{ |a| a.is_a?(Hash) } ? args.extract_options! : {} 276: protected_attributes_for_create, unprotected_attributes_for_create = {}, {} 277: args.each_with_index do |arg, i| 278: if arg.is_a?(Hash) 279: protected_attributes_for_create = args[i].with_indifferent_access 280: else 281: unprotected_attributes_for_create[attributes[i]] = args[i] 282: end 283: end 284: 285: conditions = (protected_attributes_for_create.merge(unprotected_attributes_for_create)).slice(*attributes).symbolize_keys 286: 287: record = where(conditions).first 288: 289: unless record 290: record = @klass.new(protected_attributes_for_create, options) do |r| 291: r.assign_attributes(unprotected_attributes_for_create, :without_protection => true) 292: end 293: yield(record) if block_given? 294: record.send(match.save_method) if match.save_record? 295: end 296: 297: record 298: end
# File lib/active_record/relation/finder_methods.rb, line 347 347: def find_some(ids) 348: result = where(table[primary_key].in(ids)).all 349: 350: expected_size = 351: if @limit_value && ids.size > @limit_value 352: @limit_value 353: else 354: ids.size 355: end 356: 357: # 11 ids with limit 3, offset 9 should give 2 results. 358: if @offset_value && (ids.size - @offset_value < expected_size) 359: expected_size = ids.size - @offset_value 360: end 361: 362: if result.size == expected_size 363: result 364: else 365: conditions = arel.where_sql 366: conditions = " [#{conditions}]" if conditions 367: 368: error = "Couldn't find all #{@klass.name.pluralize} with IDs " 369: error << "(#{ids.join(", ")})#{conditions} (found #{result.size} results, but was looking for #{expected_size})" 370: raise RecordNotFound, error 371: end 372: end
# File lib/active_record/relation/finder_methods.rb, line 209 209: def find_with_associations 210: join_dependency = construct_join_dependency_for_association_find 211: relation = construct_relation_for_association_find(join_dependency) 212: rows = connection.select_all(relation, 'SQL', relation.bind_values.dup) 213: join_dependency.instantiate(rows) 214: rescue ThrowResult 215: [] 216: end
# File lib/active_record/relation/finder_methods.rb, line 300 300: def find_with_ids(*ids) 301: return to_a.find { |*block_args| yield(*block_args) } if block_given? 302: 303: expects_array = ids.first.kind_of?(Array) 304: return ids.first if expects_array && ids.first.empty? 305: 306: ids = ids.flatten.compact.uniq 307: 308: case ids.size 309: when 0 310: raise RecordNotFound, "Couldn't find #{@klass.name} without an ID" 311: when 1 312: result = find_one(ids.first) 313: expects_array ? [ result ] : result 314: else 315: find_some(ids) 316: end 317: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.