::first_or_create(自 v3.2.1 起可用)按照包装盒上的说明进行操作。
Model.where(find: 'find_value').
first_or_create(create: 'create_value')
# If a record with {find: 'find_value'} already exists:
before #=> #<Model id: 1, find: "find_value", create: nil>
after #=> #<Model id: 1, find: "find_value", create: nil>
# Otherwise:
before #=> nil
after #=> #<Model id: 2, find: "find_value", create: "create_value">
如果您还希望它更新一个已经存在的记录,请尝试:
Model.where(find: 'find_value').
first_or_create(create: 'create_value').
update(update: 'update_value')
# If one already exists:
before #=> #<Model id: 1, find: "find_value", create: nil, update: nil>
after #=> #<Model id: 1, find: "find_value", create: nil, update: "update_value">
# If it already matches, no UPDATE statement will be run:
before #=> #<Model id: 1, find: "find_value", create: nil, update: "update_value">
after #=> #<Model id: 1, find: "find_value", create: nil, update: "update_value">
# Otherwise:
before #=> nil
after #=> #<Model id: 2, find: "find_value", create: 'create_value', update: "update_value">
编辑 2016-03-08:根据Doug 的comment,如果您的验证在#create 和#update 调用之间失败,或者您想最小化数据库调用,您可以使用::first_or_initialize相反,以避免在第一次调用时保留记录。但是,您必须确保在之后调用 #save 或 #update 以保留记录(我不确定 #update 是否适用于尚未保留的记录):
Model.validates :update, presence: true # The create call would fail this
Model.where(find: 'find_value').
first_or_initialize(create: 'create_value'). # doesn't call validations
update(update: 'update_value')
(注意。是一个名为#create_or_update的方法,但不要被您在Google上找到的任何documentation所迷惑;这只是#save使用的私有方法。 )