diff options
Diffstat (limited to 'activerecord/lib/active_record/relation.rb')
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 15fd1a58c8..d3f1347e03 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -94,6 +94,49 @@ module ActiveRecord scoping { @klass.create!(*args, &block) } end + # Tries to load the first record; if it fails, then <tt>create</tt> is called with the same arguments as this method. + # + # Expects arguments in the same format as <tt>Base.create</tt>. + # + # ==== Examples + # # Find the first user named Penélope or create a new one. + # User.where(:first_name => 'Penélope').first_or_create + # # => <User id: 1, first_name: 'Penélope', last_name: nil> + # + # # Find the first user named Penélope or create a new one. + # # We already have one so the existing record will be returned. + # User.where(:first_name => 'Penélope').first_or_create + # # => <User id: 1, first_name: 'Penélope', last_name: nil> + # + # # Find the first user named Scarlett or create a new one with a particular last name. + # User.where(:first_name => 'Scarlett').first_or_create(:last_name => 'Johansson') + # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'> + # + # # Find the first user named Scarlett or create a new one with a different last name. + # # We already have one so the existing record will be returned. + # User.where(:first_name => 'Scarlett').first_or_create do |user| + # user.last_name = "O'Hara" + # end + # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'> + def first_or_create(attributes = nil, options = {}, &block) + first || create(attributes, options, &block) + end + + # Like <tt>first_or_create</tt> but calls <tt>create!</tt> so an exception is raised if the created record is invalid. + # + # Expects arguments in the same format as <tt>Base.create!</tt>. + def first_or_create!(attributes = nil, options = {}, &block) + first || create!(attributes, options, &block) + end + + # Like <tt>first_or_create</tt> but calls <tt>new</tt> instead of <tt>create</tt>. + # + # Expects arguments in the same format as <tt>Base.new</tt>. + def first_or_new(attributes = nil, options = {}, &block) + first || new(attributes, options, &block) + end + alias :first_or_build :first_or_new + def respond_to?(method, include_private = false) arel.respond_to?(method, include_private) || Array.method_defined?(method) || |