在 Rails 中执行 has_one 关系

Enforce has_one relationship in Rails

我是 rails 的新手,第一次使用 has_one 协会。

用户模型

class User < ActiveRecord::Base
has_one :shop_profile
validates :user_id, presence: true
validates :user_id, uniqueness: true
end

ShopProfile 模型

class ShopProfile < ActiveRecord::Base
  belongs_to :user
end

但是我仍然可以为每个用户创建多个 ShopProfile。当用户创建第二个 shop_profile 时,它会从第一个中删除 user_id 但数据库中仍有两个

如何将用户可以拥有的 ShopProfile 数量限制为 1?

Rails 无法为您执行此操作,您可以自行查找现有记录或创建新记录,并由您确保用户不会创建第二条记录 ShopProfile 记录。这应该不是问题,您应该 post 回到正确的操作(create vs update) =] 为有问题的用户记录。如果具有现有 ShopProfile 的用户尝试 post 新的 create 操作,您应该会引发错误。


根据您的评论澄清:

这里的问题是,如果用户已经拥有个人资料,那么您是在允许用户点击个人资料的创建表单。一旦用户创建了一个配置文件,如果创建第二个配置文件的行为会导致错误,用户不应该首先让自己进入这种状态。用户拥有个人资料后,您应该将他们链接到该个人资料的 edit 视图,而不是将他们带回 create 视图一旦他们填写了表格就会产生一个错误。

可能看起来像这样:

<% if @user.shop_profile %>
  <%= link_to 'Edit Profile', [:edit, @user.shop_profile] %>
<% else %>
  <%= link_to 'Create Profile', new_shop_profile_path %>
<% end %>

如果用户 以某种方式点击了 "new" 操作来创建第二个配置文件,您应该立即阻止他们,并拒绝呈现创建表单.您的 new 操作可能看起来像这样:

def new
  if @user.shop_profile
    redirect_to edit_shop_profile_path(@user.shop_profile)
  else
    @shop_profile = ShopProfile.new
  end
end

另一种方法是,如果用户在已有配置文件时要求创建新配置文件,则您需要为他们提供一些前进的方法。这可能是您 "create" 表单上的一个复选框,让他们选择 覆盖 他们现有的个人资料。关键是,您需要为他们提供某种继续 处理您的应用程序的各种流程的方法,否则您的应用程序基本上就会崩溃。您永远不应该让用户回到他们正在填写表单但没有实际成功提交表单的地方。

我认为最好的解决方案是在注册后创建个人资料,所以在您的用户模型中放入此代码

  has_one :profile, dependent: :destroy
  after_create :create_profile

  private

  def create_profile
    Profile.create(user: self)
  end