1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
# frozen-string-literal: true
module Sequel
module Plugins
# The update_or_create plugin adds methods that make it easier
# to deal with objects which may or may not yet exist in the database.
# The first method is update_or_create, which updates an object if it
# exists in the database, or creates the object if it does not.
#
# You can call update_or_create with a block:
#
# Album.update_or_create(name: 'Hello') do |album|
# album.num_copies_sold = 1000
# end
#
# or provide two hashes, with the second one being the attributes
# to set.
#
# Album.update_or_create({name: 'Hello'}, num_copies_sold: 1000)
#
# In both cases, this will check the database to find the album with
# the name "Hello". If such an album exists, it will be updated to set
# num_copies_sold to 1000. If no such album exists, an album with the
# name "Hello" and num_copies_sold 1000 will be created.
#
# The second method is find_or_new, which returns the object from the
# database if it exists, or returns a new (unsaved) object if not. It
# has the same API as update_or_create, and operates identically to
# update_or_create except that it doesn't persist any changes.
#
# Usage:
#
# # Make all model subclass support update_or_create
# Sequel::Model.plugin :update_or_create
#
# # Make the Album class support update_or_create
# Album.plugin :update_or_create
module UpdateOrCreate
module ClassMethods
# Attempt to find an record with the +attrs+, which should be a
# hash with column symbol keys. If such an record exists, update it
# with the values given in +set_attrs+. If no such record exists,
# create a new record with the columns specified by both +attrs+ and
# +set_attrs+, with the ones in +set_attrs+ taking priority. If
# a block is given, the object is yielded to the block before the
# object is saved. Returns the new or updated object.
def update_or_create(attrs, set_attrs=nil, &block)
obj = find_or_new(attrs, set_attrs, &block)
obj.save_changes
obj
end
# Operates the same as +update_or_create+, but returns the objects
# without persisting changes (no UPDATE/INSERT queries).
def find_or_new(attrs, set_attrs=nil)
obj = find(attrs) || new(attrs)
obj.set(set_attrs) if set_attrs
yield obj if defined?(yield)
obj
end
end
end
end
end
|