Permalink
Browse files

Adding first_or_create and first_or_create! methods to ActiveRecord::…

…Relation. Related to #2420.
  • Loading branch information...
1 parent 827a0fe commit 4f229743c631c7421d24b0d794660359e8afe8fe @andmej committed Aug 28, 2011
@@ -442,6 +442,7 @@ class Base
class << self # Class methods
delegate :find, :first, :first!, :last, :last!, :all, :exists?, :any?, :many?, :to => :scoped
+ delegate :first_or_create, :first_or_create!, :to => :scoped
delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, :to => :scoped
delegate :find_each, :find_in_batches, :to => :scoped
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
@@ -94,6 +94,14 @@ def create!(*args, &block)
scoping { @klass.create!(*args, &block) }
end
+ def first_or_create(*args, &block)
+ first || create(*args, &block)
+ end
+
+ def first_or_create!(*args, &block)
+ first || create!(*args, &block)
+ end
+
def respond_to?(method, include_private = false)
arel.respond_to?(method, include_private) ||
Array.method_defined?(method) ||
@@ -863,6 +863,38 @@ def test_create_bang
assert_equal 'hen', hen.name
end
+ def test_first_or_create
+ assert Bird.respond_to?(:first_or_create)
+
+ parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
+ assert_kind_of Bird, parrot
+ assert parrot.persisted?
+ assert_equal 'parrot', parrot.name
+ assert_equal 'green', parrot.color
+
+ the_same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
+ assert_kind_of Bird, the_same_parrot
+ assert the_same_parrot.persisted?
+ assert_equal parrot, the_same_parrot
+ end
+
+ def test_first_or_create_bang
+ assert Bird.respond_to?(:first_or_create!)
+
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
+
+ parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
+ assert_kind_of Bird, parrot
+ assert parrot.persisted?
+ assert_equal 'parrot', parrot.name
+ assert_equal 'green', parrot.color
+
+ the_same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
+ assert_kind_of Bird, the_same_parrot
+ assert the_same_parrot.persisted?
+ assert_equal parrot, the_same_parrot
+ end
+
def test_explicit_create_scope
hens = Bird.where(:name => 'hen')
assert_equal 'hen', hens.new.name

0 comments on commit 4f22974

Please sign in to comment.