1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add find_or_create_by_* and find_or_initialize_by_* to relations

This commit is contained in:
Pratik Naik 2009-12-27 14:28:19 +05:30
parent 8829d6ecc6
commit d511de0261
2 changed files with 44 additions and 0 deletions

View file

@ -142,6 +142,8 @@ module ActiveRecord
if match.finder?
find_by_attributes(match, attributes, *args)
elsif match.instantiator?
find_or_instantiator_by_attributes(match, attributes, *args, &block)
end
else
super
@ -159,6 +161,27 @@ module ActiveRecord
end
end
def find_or_instantiator_by_attributes(match, attributes, *args)
guard_protected_attributes = false
attributes_for_create = conditions = attributes.inject({}) {|h, a| h[a] = args[attributes.index(a)]; h}
if args[0].is_a?(Hash)
guard_protected_attributes = true
conditions = args[0].with_indifferent_access.slice(*attributes).symbolize_keys
end
record = where(conditions).first
unless record
record = @klass.new { |r| r.send(:attributes=, attributes_for_create, guard_protected_attributes) }
yield(record) if block_given?
record.save if match.instantiator == :create
end
record
end
def create_new_relation(relation, readonly = @readonly, preload = @associations_to_preload, eager_load = @eager_load_associations)
Relation.new(@klass, relation, readonly, preload, eager_load)
end

View file

@ -254,5 +254,26 @@ class RelationTest < ActiveRecord::TestCase
assert_kind_of Array, davids
assert_equal [authors(:david)], davids
end
def test_dynamic_find_or_initialize_by_attributes
authors = Author.scoped
lifo = authors.find_or_initialize_by_name('Lifo')
assert_equal "Lifo", lifo.name
assert lifo.new_record?
assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David')
end
def test_dynamic_find_or_create_by_attributes
authors = Author.scoped
lifo = authors.find_or_create_by_name('Lifo')
assert_equal "Lifo", lifo.name
assert ! lifo.new_record?
assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
end
end