has_one关联在rails中创建多个记录

时间:2017-09-28 03:57:32

标签: ruby-on-rails ruby activerecord rails-activerecord

我有一个用户模型和商店模型。我想允许用户只创建一个商店。所以在我的用户模型中

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  validates :terms_and_conditions, :acceptance => true
  has_one :shop
end

我的店铺模特看起来像这样

class Shop < ApplicationRecord
  has_many :products, dependent: :destroy
  belongs_to :user
end

但是如果我尝试为已经拥有一个商店的用户创建一个新商店,那么从控制台开始,没有错误并且成功提交。

[
  #<Shop id: 1, name: "Rabin & Rose Shop", location: "Banepa Kavre Nepal", description: "oho k vhk kl;o jjio ko;k; jljlkj", rating: nil, delivery_service: true, user_id: 1, created_at: "2017-09-27 15:31:57", updated_at: "2017-09-27 15:31:57", img_url: nil>, 
  #<Shop id: 2, name: "jhoney", location: "sins shop", description: "the entire fuck history here", rating: nil, delivery_service: true, user_id: 1, created_at: "2017-09-28 00:55:44", updated_at: "2017-09-28 00:55:44", img_url: nil>, 
  #<Shop id: 3, name: "Thakur Shop", location: "Pulbazar banepa", description: "Our shop has chicken bedroom. you can met call gir...", rating: nil, delivery_service: true, user_id: 2, created_at: "2017-09-28 01:50:40", updated_at: "2017-09-28 01:50:40", img_url: nil>, 
  #<Shop id: 4, name: nil, location: nil, description: nil, rating: nil, delivery_service: true, user_id: 1, created_at: "2017-09-28 03:49:34", updated_at: "2017-09-28 03:49:34", img_url: nil>
]

user_id = 1有多条记录。

1 个答案:

答案 0 :(得分:2)

Rails关联方法(has_onehas_many等等)不验证您的数据。这意味着,仍然可以插入数据,因为您没有在应用程序层或数据层对传入数据进行验证。

为了限制用户拥有多个商店,您必须在数据层添加唯一索引,并在必要时在应用程序层进行唯一性验证。一旦到位,数据库就不允许为一个特定用户创建多个商店。

迁移的唯一索引应该类似于

add_index :shops, :user_id, unique: true

使用该索引,数据库将不允许插入带有重复user_id的商店记录。

在应用程序层,您可以在用户或Shop上的user_id上添加唯一性验证,或在User上添加检查shop是否存在的验证如果验证失败,请添加错误。

这是

的一个例子
class Shop < ApplicationRecord
  validate :one_shop_per_user

  private

  def one_shop_per_user
     if user.shop && user.shop != self
       errors.add(:user, "already has a shop")
     end
  end
end

请注意,这只是实现您想要做的事情的众多解决方案之一。