Commit
Add first_or_create family of methods to Active Record
- Loading branch information
There are no files selected for viewing
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
|
@@ -94,6 +94,49 @@ def create!(*args, &block) | ||
scoping { @klass.create!(*args, &block) } | scoping { @klass.create!(*args, &block) } | ||
end | 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) | |||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jonleighton
Author
Member
|
|||
first || new(attributes, options, &block) | |||
end | |||
alias :first_or_build :first_or_new | |||
|
|||
def respond_to?(method, include_private = false) | def respond_to?(method, include_private = false) | ||
arel.respond_to?(method, include_private) || | arel.respond_to?(method, include_private) || | ||
Array.method_defined?(method) || | Array.method_defined?(method) || | ||
|
Shouldn't this be called
first_or_initialize
in order to be consistent withfind_or_initialize_by_name
? I would prefer that thanfirst_or_new
orfirst_or_build
(which makes you think they are different but they are not).