我有User
has_one Widget
。
class User
has_one :widget, :dependent => :destroy
end
class Widget
belongs_to :user
end
当我为Widget
创建新的User
时,我想销毁与User
相关联的旧版本。
这是我的情况:
创建用户:
user = User.new
user.save
user # => #<User id: 1>
创建用户的小部件:
widget = Widget.new
widget.user = user
widget.save
重新加载并检查小部件:
user.reload
user.widget # => #<Widget id: 1, user_id: 1>
构建一个小部件,注意现有小部件在另一个保存之前被销毁:
user.build_widget # => #<Widget id: nil, user_id: 1>
user.reload
user.widget # => nil
重新创建用户的小部件:
user.create_widget # => #<Widget id: 2, user_id: 1>
创建另一个小部件:
widget = Widget.new :user => user
widget.save
现在,两者都存在:
Widget.find(2) # => #<Widget id: 2, user_id: 1>
Widget.find(3) # => #<Widget id: 3, user_id: 1>
用户是第一个:
user.reload
user.widget # => #<Widget id: 2, user_id: 1>
有没有办法做到这一点:
def create
@widget = current_user.build_widget(params[:widget])
respond_to do |format|
if @widget.save
format.html { redirect_to widget_path, notice: 'Widget was successfully created.' }
format.json { render json: @widget, status: :created, location: @widget }
else
format.html { render action: 'new' }
format.json { render json: @widget.errors, status: :unprocessable_entity }
end
end
end
在保存之前不删除旧小部件,或者:
def create
@widget = Widget.new(params[:widget])
@widget.user = current_user
respond_to do |format|
if @widget.save
format.html { redirect_to widget_path, notice: 'Widget was successfully created.' }
format.json { render json: @widget, status: :created, location: @widget }
else
format.html { render action: 'new' }
format.json { render json: @widget.errors, status: :unprocessable_entity }
end
end
端
没有保留两份副本?
我不想用像
这样的交易搞砸我的控制器Widget.transaction do
old_widget.destroy
new_widget.save
end
但到目前为止,这似乎是唯一的方法。
答案 0 :(得分:0)
看起来您有两个使用路径,用户可以在其中创建窗口小部件。从用户端和小部件方面。如果你通过一段代码将它们汇集起来会更好,并进行一些唯一性验证,以确保没有滑倒。
如何在user.create_widget中查找find_or_create_by,以便您可以编辑现有小部件(如果需要更新)或创建新小部件。
答案 1 :(得分:0)
您应该更新 widget
的现有 user
记录,而不是创建新记录并销毁旧记录。
你可以这样做:
class User
has_one :widget, :dependent => :destroy
def assign_widget(attr_hash)
widget ? widget.update(attr_hash) : widget.create(attr_hash)
widget.reload
end
end