Ruby on rails 3 ActiveRecord:如果存在,则更新记录。是否创建?
正在尝试在活动记录中实现create if not EXCESS update记录 当前使用:Ruby on rails 3 ActiveRecord:如果存在,则更新记录。是否创建?,ruby-on-rails-3,activerecord,Ruby On Rails 3,Activerecord,正在尝试在活动记录中实现create if not EXCESS update记录 当前使用: @student = Student.where(:user_id => current_user.id).first if @student Student.destroy_all(:user_id => current_user.id) end Student = Student.new(:user_id => current_user.id, :department
@student = Student.where(:user_id => current_user.id).first
if @student
Student.destroy_all(:user_id => current_user.id)
end
Student = Student.new(:user_id => current_user.id, :department => 1
)
Student.save!
如果记录存在或创建,更新记录的正确方法是什么 您可能正在寻找
first\u或\u create
或类似的内容:
如果用户和学生之间有关联,这会更漂亮。类似于
@student = current_user.student || current_user.build_student
@student.department_id = 1
@student.save
编辑:
您也可以使用Sevensacat的回答,但您仍然需要处理不同的场景,例如更新学生的部门id
更新:
你可以用
它是“查找”或“创建”,而不是“先查找”或“创建”。
前任: 客户端。在Rails 4中查找或创建(名字:“Andy”)
Student.
find_or_initialize_by(:user_id => current_user.id).
update_attributes!(:department => 1)
::first_或_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">
(注意,有一种方法叫做
#create\u或#update
,但不要被你在谷歌上找到的任何方法所愚弄;这只是#save
使用的一种私有方法)不幸的是,我认为最干净的方法是:
Student.where(user_id: id).first_or_create(age: 16).update_attribute(:age, 16)
在Rails 5中
Student.
find_or_initialize_by(:user_id => current_user.id).
update(:department => 1)
(从@Zorayr answer获得所有积分)。first\u或\u create不会更新记录,因此它不会使代码变得更好。但它会返回找到的或创建的记录,因此您可以将
update
调用链接到它。请参阅本页的。这会导致创建时的验证出现问题,并导致两个单独的db事务。来自@Zorayr的答案更可取,因为它尊重验证。这是真的。要通过验证,我认为您可以使用first\u或\u initialize
,方法与first\u或\u create
完全相同;但是你必须对结果调用save
或update
。@rune schjellerup philosof,但你可以在之后更新它。首先\u或\u创建(用户id:current\u user.id,部门:1)。更新(部门:1)
确实存在,(即使在一年前),我不确定你想用这个答案说什么,但这听起来像是对另一篇文章的评论,两者的作用也略有不同Model.where(find:'find_value')。first_或_create(create:'create_value')
相当于Model.find_或_create_by(find:'find_value'){| r | r.create='create_value'}
查找或_初始化+更新_属性代码>将执行以下操作更新属性的返回值代码>是一个布尔值,而不是实际记录。您可以使用Student.find_或_initialize_by(…).tap{e|e.update!(…)}
有两个问题-首先,您无法“仅在创建时设置值”,其次,它查看表列而不是模型方法。例如,User.where(email:email).find_或_initialize_by(password:password)
会给您一个列users.password不存在的错误(假设您是明智的,并且没有在数据库中存储普通密码)。这是一个不错的解决方案。在Rails 4中,我只会将.update\u attributes
更改为.update
。这是一种惯用的方法,源代码显示它与.update\u属性相同!(它只需分配属性并调用.save
…检查和)。
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">
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')
Student.where(user_id: id).first_or_create(age: 16).update_attribute(:age, 16)
Student.
find_or_initialize_by(:user_id => current_user.id).
update(:department => 1)