开发者

Maximum number of associated records

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 curre开发者_JAVA技巧ntly using a custom method with ActiveRecord::Base.connection and calling that instead of .create or .save when new_record? == true.


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜