Skip to content
This repository
Browse code

Add find(ids) to relations

  • Loading branch information...
commit d92c4a84023bc0c8dd75869c9b4d5e50277f4650 1 parent 81608cf
Pratik lifo authored
6 activerecord/CHANGELOG
... ... @@ -1,5 +1,11 @@
1 1 *Edge*
2 2
  3 +* Add find(ids) to relations. [Pratik Naik]
  4 +
  5 + old_users = User.order("age DESC")
  6 + old_users.find(1)
  7 + old_users.find(1, 2, 3)
  8 +
3 9 * Add new finder methods to association collection. [Pratik Naik]
4 10
5 11 class User < ActiveRecord::Base
63 activerecord/lib/active_record/relation.rb
@@ -91,7 +91,7 @@ def to_a
91 91 :joins => @relation.joins(relation),
92 92 :group => @relation.send(:group_clauses).join(', '),
93 93 :order => @relation.send(:order_clauses).join(', '),
94   - :conditions => @relation.send(:where_clauses).join("\n\tAND "),
  94 + :conditions => where_clause,
95 95 :limit => @relation.taken,
96 96 :offset => @relation.skipped
97 97 },
@@ -111,6 +111,25 @@ def to_a
111 111
112 112 alias all to_a
113 113
  114 + def find(*ids, &block)
  115 + return to_a.find(&block) if block_given?
  116 +
  117 + expects_array = ids.first.kind_of?(Array)
  118 + return ids.first if expects_array && ids.first.empty?
  119 +
  120 + ids = ids.flatten.compact.uniq
  121 +
  122 + case ids.size
  123 + when 0
  124 + raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
  125 + when 1
  126 + result = find_one(ids.first)
  127 + expects_array ? [ result ] : result
  128 + else
  129 + find_some(ids)
  130 + end
  131 + end
  132 +
114 133 def first
115 134 if loaded?
116 135 @records.first
@@ -183,9 +202,51 @@ def find_or_instantiator_by_attributes(match, attributes, *args)
183 202 record
184 203 end
185 204
  205 + def find_one(id)
  206 + record = where(@klass.primary_key => id).first
  207 +
  208 + unless record
  209 + conditions = where_clause(', ')
  210 + conditions = " [WHERE #{conditions}]" if conditions.present?
  211 + raise RecordNotFound, "Couldn't find #{@klass.name} with ID=#{id}#{conditions}"
  212 + end
  213 +
  214 + record
  215 + end
  216 +
  217 + def find_some(ids)
  218 + result = where(@klass.primary_key => ids).all
  219 +
  220 + expected_size =
  221 + if @relation.taken && ids.size > @relation.taken
  222 + @relation.taken
  223 + else
  224 + ids.size
  225 + end
  226 +
  227 + # 11 ids with limit 3, offset 9 should give 2 results.
  228 + if @relation.skipped && (ids.size - @relation.skipped < expected_size)
  229 + expected_size = ids.size - @relation.skipped
  230 + end
  231 +
  232 + if result.size == expected_size
  233 + result
  234 + else
  235 + conditions = where_clause(', ')
  236 + conditions = " [WHERE #{conditions}]" if conditions.present?
  237 +
  238 + error = "Couldn't find all #{@klass.name.pluralize} with IDs "
  239 + error << "(#{ids.join(", ")})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
  240 + raise RecordNotFound, error
  241 + end
  242 + end
  243 +
186 244 def create_new_relation(relation, readonly = @readonly, preload = @associations_to_preload, eager_load = @eager_load_associations)
187 245 Relation.new(@klass, relation, readonly, preload, eager_load)
188 246 end
189 247
  248 + def where_clause(join_string = "\n\tAND ")
  249 + @relation.send(:where_clauses).join(join_string)
  250 + end
190 251 end
191 252 end
24 activerecord/test/cases/relations_test.rb
@@ -275,5 +275,27 @@ def test_dynamic_find_or_create_by_attributes
275 275 assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
276 276 end
277 277
278   -end
  278 + def test_find_id
  279 + authors = Author.scoped
  280 +
  281 + david = authors.find(authors(:david).id)
  282 + assert_equal 'David', david.name
  283 +
  284 + assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('invalid') }
  285 + end
279 286
  287 + def test_find_ids
  288 + authors = Author.order('id ASC')
  289 +
  290 + results = authors.find(authors(:david).id, authors(:mary).id)
  291 + assert_kind_of Array, results
  292 + assert_equal 2, results.size
  293 + assert_equal 'David', results[0].name
  294 + assert_equal 'Mary', results[1].name
  295 + assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
  296 +
  297 + assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, 'invalid') }
  298 + assert_raises(ActiveRecord::RecordNotFound) { authors.find(['invalid', 'oops']) }
  299 + end
  300 +
  301 +end

0 comments on commit d92c4a8

Please sign in to comment.
Something went wrong with that request. Please try again.