更新关联时如何销毁其他 has_one 关系?

发布于 2024-12-02 00:33:25 字数 2577 浏览 1 评论 0原文

我有一个 User,它 has_one Widget

class User
  has_one :widget, :dependent => :destroy
end

class Widget
  belongs_to :user
end

当我为 User 创建一个新的 Widget 时,我想销毁与 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

,但到目前为止,这似乎是唯一的方法。

I have a User which has_one Widget.

class User
  has_one :widget, :dependent => :destroy
end

class Widget
  belongs_to :user
end

And when I create a new Widget for a User, I want to destroy the old one associated with the User.

Here's my situation:

Create a user:

user = User.new
user.save
user # => #<User id: 1>

Create user's widget:

widget = Widget.new
widget.user = user
widget.save

Reload and check the widget:

user.reload
user.widget # => #<Widget id: 1, user_id: 1>

Build a widget, notice that the existing widget is destroyed before the other is saved:

user.build_widget # => #<Widget id: nil, user_id: 1>
user.reload
user.widget # => nil

Recreate user's widget:

user.create_widget # => #<Widget id: 2, user_id: 1>

Create another widget:

widget = Widget.new :user => user
widget.save

Now, both exist:

Widget.find(2) # => #<Widget id: 2, user_id: 1>
Widget.find(3) # => #<Widget id: 3, user_id: 1>

And user's is the first:

user.reload
user.widget # => #<Widget id: 2, user_id: 1>

Is there any way to do this:

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

without deleting the old widget before saving, or this:

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

end

without keeping two copies around?

I don't want to muck up my controllers with transactions like

Widget.transaction do
  old_widget.destroy
  new_widget.save
end

but so far, this seems like the only way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

所谓喜欢 2024-12-09 00:33:25

看起来您有两个使用路径,用户可以在其中创建小部件。从用户端和小部件端。如果您通过一段代码将它们集中起来,并进行一些唯一性验证以确保不会出现任何失误,那就更好了。

在 user.create_widget 中使用 find_or_create_by 怎么样,以便您可以在需要更新现有小部件或创建新小部件时对其进行编辑。

It looks like you have two usage paths where a user can create widgets. From the user side and from the widget side. It would be better if you funneled them through one piece of code, and put some uniqueness validations up to insure there are no slip ups.

how about a find_or_create_by in user.create_widget so that you can edit the existing widget if it needs to be updated or you create a new one.

萌逼全场 2024-12-09 00:33:25

您应该更新用户现有的widget记录,而不是创建新记录并销毁旧记录。
你可以这样做:

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

You should update the existing widget record for the user instead of creating a new one and destroying the old one.
You can do something like this:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文