最大关联记录数

发布于 2024-10-31 02:20:22 字数 588 浏览 0 评论 0原文

我希望模型上有最大数量的关联记录。 例如,一个项目有很多任务,但不超过二十个。

我如何执行此规则?

到目前为止我能想到的唯一解决方案是 INSERT INTO...SELECT 查询如下:

INSERT INTO
  tasks (`id`,`project_id`,`title`,`body`)
SELECT
  NULL, ?, ?, ?
FROM
  tasks
HAVING
  count(id) < MAX_NUMBER_OF_TASKS
LIMIT 1;
  1. 据我所知,这将保证插入最大数量的任务。我的说法正确吗?
  2. 有没有“Rails 方式”来做到这一点?
  3. 是否可以覆盖 ActiveRecord/Task 模型,以便它使用上面的查询 插入新记录?

我目前正在使用 ActiveRecord::Base.connection 的自定义方法 并在 new_record? 时调用它而不是 .create.save? == true

I'd like to have a maximum number of associated records on a model.
E.g. a project has_many tasks, but not more then twenty.

How can I enforce this rule?

The only solution that I've been able to come up with so far is an
INSERT INTO...SELECT query like this:

INSERT INTO
  tasks (`id`,`project_id`,`title`,`body`)
SELECT
  NULL, ?, ?, ?
FROM
  tasks
HAVING
  count(id) < MAX_NUMBER_OF_TASKS
LIMIT 1;
  1. As far as I can tell, this will guarantee a maximum number of tasks being inserted. Am I correct in this?
  2. Is there a 'Rails way' to do this?
  3. Is it possible to override ActiveRecord/the Task model so that it uses the query above
    to insert a new record?

I'm currently using a custom method with ActiveRecord::Base.connection
and calling that instead of .create or .save when new_record? == true.

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

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

发布评论

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

评论(2

猥琐帝 2024-11-07 02:20:22

我没能尝试这个,但我不明白为什么它不起作用。

第一步:在父对象上定义一个验证器(这是一个简单的实现 - 可以/应该变得更通用):

class Project < ActiveRecord::Base
  validate :max_tasks

  def max_tasks
    if tasks.count > 20
      errors.add_to_base("Should not have more than 20 tasks")
    end
  end
end

第二步:从任务中打开项目验证:

class Task < ActiveRecord::Base
  validates_associated :project
end

我认为你应该开始做生意。当您尝试保存新任务时,它将验证关联的项目,如果(现在)关联的任务超过 20 个,则验证将失败。

如果你想让它更通用,你可以这样做:

class NumberOfAssociatedValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if options[:maximum] && record.send(attribute).count > options[:maximum]
      record.errors[attribute] << "must not have more than #{options[:maximum]}"
    end
    if options[:minimum] && record.send(attribute).count < options[:minimum]
      record.errors[attribute] << "must not have less than #{options[:minimum]}"
    end
  end
end

class MyModel < ActiveRecord::Base
  validates :my_association, :number_of_associated => {:maxiumum => 20}
end

I haven't been able to try this, but I can't see why it shouldn't work.

Step one: Define a validator on the parent object (this is a simple implementation - could/should be made more generic):

class Project < ActiveRecord::Base
  validate :max_tasks

  def max_tasks
    if tasks.count > 20
      errors.add_to_base("Should not have more than 20 tasks")
    end
  end
end

Step two: Turn on validation of project from tasks:

class Task < ActiveRecord::Base
  validates_associated :project
end

And I think you should be in business. When you try and save a new task, it'll validate the associated project, and the validation will fail if there are (now) more than 20 tasks associated.

Just in case you fancy making this more generic, you could do something like:

class NumberOfAssociatedValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if options[:maximum] && record.send(attribute).count > options[:maximum]
      record.errors[attribute] << "must not have more than #{options[:maximum]}"
    end
    if options[:minimum] && record.send(attribute).count < options[:minimum]
      record.errors[attribute] << "must not have less than #{options[:minimum]}"
    end
  end
end

class MyModel < ActiveRecord::Base
  validates :my_association, :number_of_associated => {:maxiumum => 20}
end
明月夜 2024-11-07 02:20:22

也许您可以向模型添加一些预保存验证,以检查它已有的关联模型数量,并在超过最大关联数时抛出验证错误。

May be you can add some pre save validation to your model, that checks how many associated models it already have, and throw a validation error if it exceeds your max number of associations.

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