【问题标题】:How to prevent saving invalid ids in associative table in Rails?如何防止在 Rails 的关联表中保存无效 ID?
【发布时间】:2018-02-06 16:36:04
【问题描述】:

我的 Rails 应用程序中有两个表:CategoryService。我还在它们之间创建了一个关联表CategoriesService,除了验证CategoriesService 表上的ID 之外,一切正常——我只是注意到我能够创建与不存在的记录的关联。我想知道如何才能正确修复它——我怀疑 Rails 应该让我们创建一些数据库级别的验证,这可能会更快更干净。我是这样定义我的模型的:

class Category < ApplicationRecord
  has_and_belongs_to_many :services
end

class Service < ApplicationRecord
  has_and_belongs_to_many :categories
end

class CategoriesService < ApplicationRecord
end

我在想创建has_and_belongs_to_many 关系可以确保这种验证本身,但我知道我错了。我该如何解决这个问题?

【问题讨论】:

    标签: ruby-on-rails validation many-to-many


    【解决方案1】:

    来自Rails style guide

    更喜欢has_many :through 而不是has_and_belongs_to_many。使用has_many :through 允许在连接模型上进行附加属性和验证。

    在你的情况下:

    class Category < ApplicationRecord
      has_many :categories_services
      has_many :services, through: :categories_services
    end
    
    class Service < ApplicationRecord
      has_many :categories_services
      has_many :categories, through: :categories_services
    end
    
    class CategoriesService < ApplicationRecord
      belongs_to :category
      belongs_to :service
    
      # if not using Rails 5:
      validates :category, presence: true
      validates :service, presence: true
      # if using Rails 5, a `belongs_to` will auto-validate the presence
    end
    

    使用连接模型(而不是has_and_belongs_to_many),您可以更好地控制多对多关系:

    • 您(可以)在连接表上拥有 created_atupdated_at 字段,它们像往常一样由 Rails 自动管理
    • 您可以改进您的连接模型,例如,拥有一个列position,然后您可以提供对特定categoryservicesfavorite 布尔列等进行排序的功能。

    此外,您可以(我建议您这样做)通过在数据库中添加一些约束来强制执行此验证:

    # PostgreSQL
    CREATE TABLE categories_services (
      id SERIAL PRIMARY KEY,
      category_id integer REFERENCES categories NOT NULL,
      service_id integer REFERENCES services NOT NULL,
      created_at timestamp NOT NULL DEFAULT now(),
      updated_at timestamp NOT NULL DEFAULT now()
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多